Merge branch 'mc1.18/0.5.1' into mc1.18/0.5.1-repolish

This commit is contained in:
simibubi 2023-03-01 21:52:11 +01:00
commit dde9ad280b
139 changed files with 3314 additions and 1132 deletions

View file

@ -2,18 +2,15 @@
f0d6baaabda94151134f569246d61a6e710c35a9 assets/create/blockstates/acacia_window_pane.json
6b70306397316d6ebfa1cb07f2308d5c7fce83e0 assets/create/blockstates/adjustable_chain_gearshift.json
9dd79bf5430f674e7d3e3fc7d59edee3d66e241e assets/create/blockstates/analog_lever.json
a891d5abbc133288a9ad377b3ea9adad8ee92972 assets/create/blockstates/andesite_alloy_block.json
951d67fc41af364e333babf649e1a04beea6226a assets/create/blockstates/andesite_bars.json
47cb4f4629277b467263bd54a44dec45837eb719 assets/create/blockstates/andesite_belt_funnel.json
96097d97028f38d61d64fec7c7095aaf64650db3 assets/create/blockstates/andesite_belt_funnel.json
9999a75c7766781eadb12510a09264600bc846e4 assets/create/blockstates/andesite_casing.json
96bd534d3d84336927fb6512f9848d837d557084 assets/create/blockstates/andesite_encased_cogwheel.json
1673172100317477ca559c32fd91d16b165e0085 assets/create/blockstates/andesite_encased_large_cogwheel.json
9639b901ffdd2ecccab5575c5c9e6c7b5c901e02 assets/create/blockstates/andesite_encased_shaft.json
7c5ac6149a991dfe125be3ae3c27c0c841e11f6c assets/create/blockstates/andesite_funnel.json
ca9a629472625abf741f02b94ce4578292fb14a7 assets/create/blockstates/andesite_funnel.json
73154ab9fe5463116d06d0732f9a1c2fa817dc3f assets/create/blockstates/andesite_ladder.json
3adca59d03198c273f13c21c6058348c9fa71735 assets/create/blockstates/andesite_pillar.json
a07a73251d26e8b38bce295838c2fef246f9885d assets/create/blockstates/andesite_scaffolding.json
98e95355fc7d45fc9d3706ed3912cd0bfb4a41c3 assets/create/blockstates/andesite_tunnel.json
1d2d8081581e07d9be4b382aede4f2de4401cc6b assets/create/blockstates/andesite_tunnel.json
70a2eff30918c6369fc90aaa6a56ffa5c959065a assets/create/blockstates/asurine.json
bb61f3f336ebe0ff08d84cb6a83e86a823dac7aa assets/create/blockstates/asurine_pillar.json
e555e3c2b2d3f01440e48db4ba88f7e00fd99b6f assets/create/blockstates/basin.json
@ -31,17 +28,15 @@ ec2ab87734acc209e6be3bc4898b1199f819bfd3 assets/create/blockstates/blue_sail.jso
4854d1ef52130a7887aecc60bcaffbd66f0871a8 assets/create/blockstates/blue_seat.json
dea175335c5db0abe758cd208dc984c22506a176 assets/create/blockstates/blue_toolbox.json
f3697a7d105e5d271f5999b86df071fe5893457c assets/create/blockstates/blue_valve_handle.json
73648bfbc15c536613ca92fb675c17243d9f4f44 assets/create/blockstates/brass_bars.json
4b436e4afa3b1734567010788064fee73f69c92e assets/create/blockstates/brass_belt_funnel.json
5f57741e500903b70c80d2a72788a25e97387e2e assets/create/blockstates/brass_belt_funnel.json
8b1dd00adcc7e74c5a9feed069e2610b15a338cb assets/create/blockstates/brass_block.json
b8dd6e505943e06706d0718ece620ab3cf943650 assets/create/blockstates/brass_casing.json
577adb030af119fb980ededaa7fc2a3d3ed14220 assets/create/blockstates/brass_encased_cogwheel.json
e69a71fdeb5855b2a59a31598f25eaea589c1748 assets/create/blockstates/brass_encased_large_cogwheel.json
288bad07593a8a2c8efaf44bba0ffb0011d36cd3 assets/create/blockstates/brass_encased_shaft.json
bd8f3073f3208d0116719a25044a91dd46fc11ac assets/create/blockstates/brass_funnel.json
adfbd6cc5e44a0f431180aedbe65a19428299d8e assets/create/blockstates/brass_funnel.json
f9234ab4324892587c4b0bf38523ee7770072f6b assets/create/blockstates/brass_ladder.json
1424ae41182927e71613a6495530c1ec346e8f50 assets/create/blockstates/brass_scaffolding.json
769e12a65262f79b57df9e3300df20d3fca6c3bb assets/create/blockstates/brass_tunnel.json
672eedcd3520c6d39603449165a23be9c612c620 assets/create/blockstates/brass_tunnel.json
ffe31d5ad0486949b049cf2060d1f34ef7ceaa82 assets/create/blockstates/brown_nixie_tube.json
11ebdd9bd0815833e62ec1bea03a4cdd86ce00f3 assets/create/blockstates/brown_sail.json
e81608346d43406ee72cae0f78b8bcfb37ba2d75 assets/create/blockstates/brown_seat.json
@ -59,10 +54,8 @@ e5e3757e99c139d67b2a70288466d8a74d818841 assets/create/blockstates/cogwheel.json
7d11142092c89ccba3e74e0a3bdd0ccb446d63b5 assets/create/blockstates/controller_rail.json
80d71365995d4c2a61dd1c15e99cae18551af6e8 assets/create/blockstates/controls.json
961b615124ea9a5a5735e8a79f81a702de7da2cf assets/create/blockstates/copper_backtank.json
977c993fbcebf7d321eaa6840f179f6c9a155148 assets/create/blockstates/copper_bars.json
cabf6b8c59eb0e3d56a0a5a856ca058bb3200882 assets/create/blockstates/copper_casing.json
a54d18937f8ce000f7ed0dc627d6d3414805006a assets/create/blockstates/copper_ladder.json
9d264bda40584003a183c386264117829279d21b assets/create/blockstates/copper_scaffolding.json
b3d0dee8f6e14fa6c637e98cc1c6f1ea55b5f0d5 assets/create/blockstates/copper_shingle_slab.json
a002289d0bb7df6927e8e6a99e9eb9ec77bd179d assets/create/blockstates/copper_shingle_stairs.json
7db3cd84768bf2dcb8420cbf45492f543ddfd893 assets/create/blockstates/copper_shingles.json
@ -70,7 +63,6 @@ a87097f3a092264d9b74966ee9e3bcfc0b743f80 assets/create/blockstates/copper_tile_s
1cc9cdcd48ea76fe3407dce0973220ff9f63f51a assets/create/blockstates/copper_tile_stairs.json
cbae7653d6a6f2d98370e9a4a3bd91fdb529f89d assets/create/blockstates/copper_tiles.json
543af282e2cb44f00509d850814b4501f3491d48 assets/create/blockstates/copper_valve_handle.json
ce4968cbe65f267c27902372075265c5cdd1b285 assets/create/blockstates/copycat_bars.json
22a91cc73d6b492dddd9354693b873701fb82c01 assets/create/blockstates/copycat_base.json
f4d185b9eb086e5024a9818bad57d524267d6e13 assets/create/blockstates/copycat_panel.json
f4d185b9eb086e5024a9818bad57d524267d6e13 assets/create/blockstates/copycat_step.json
@ -81,7 +73,7 @@ f0031f5e970b3d5695472ed384950b8631b015ed assets/create/blockstates/creative_moto
f7c283460879e70ed0fa112a24caa06a7122358f assets/create/blockstates/crimsite_pillar.json
24ee16e3dadb3e0221afce7af37643494f471fb0 assets/create/blockstates/crimson_window.json
3e6cd0945390b390b963474f7cf708e2dcba631c assets/create/blockstates/crimson_window_pane.json
644cc650c49602e654e85b3b05073748c6cd42e5 assets/create/blockstates/crushing_wheel.json
fe2f78b94c20944399101e7369e2d43324297fb6 assets/create/blockstates/crushing_wheel.json
a1dd6cb3daa97ea871290ef7b178d28b564ee2a2 assets/create/blockstates/crushing_wheel_controller.json
b1126c191877cff86b4e2de83e1fcbd151451cb7 assets/create/blockstates/cuckoo_clock.json
7b4147b215d676a528ee8782a4528d42dac02198 assets/create/blockstates/cut_andesite.json
@ -253,14 +245,12 @@ f1da8d16c9b0122bda60583a03d2b31ec1c70799 assets/create/blockstates/green_valve_h
be3bef7e091d8b50bfc1c6b7275946d1f636aefd assets/create/blockstates/horizontal_framed_glass.json
18d9fdaa1352a7e2ec91135e46dae5c02ccd8f8f assets/create/blockstates/horizontal_framed_glass_pane.json
30ec347dfc827a9ae52cf3da964b828005acede1 assets/create/blockstates/hose_pulley.json
1625a5838bd891fe6950dcb7b4235b4a53976a7d assets/create/blockstates/industrial_iron_block.json
6651c84ea621777d572a3d7aa13b75d9f061191b assets/create/blockstates/item_drain.json
10ef455fd61ed1ca831d27bf2b533d05dec9c67d assets/create/blockstates/item_vault.json
5d851c90d23de5087ce546d4bbe509e112b84c49 assets/create/blockstates/jungle_window.json
b15bea757ef981e0ca60f740ca234ee2014eb7b7 assets/create/blockstates/jungle_window_pane.json
a922b31bc4a91f5825b643ba5fa2c9a836d612cd assets/create/blockstates/large_bogey.json
f651091db216b009b3379b2f48d56d03481c8675 assets/create/blockstates/large_cogwheel.json
9554c8d14271a2b85df7eadeceaa8b31849415e4 assets/create/blockstates/large_water_wheel.json
a38184e035c2ebca7471e1714494fea213af259e assets/create/blockstates/layered_andesite.json
2409f04042380a8ad086f9c4f98032e85771c3f3 assets/create/blockstates/layered_asurine.json
ca1648840d9f5786f85e4214a0951306c1247c73 assets/create/blockstates/layered_calcite.json
@ -304,13 +294,14 @@ bff90a8d674a839b13fd9cd1f78bf3d0ad9fad4f assets/create/blockstates/limestone_pil
ddcf4bb281e046fbb1026b8f46a2cf12448598df assets/create/blockstates/mechanical_bearing.json
5586beef2d9183dc34d8e8d2723620c0569592ae assets/create/blockstates/mechanical_crafter.json
0cfa8a4a37f4142fa07e04666e0aef080c517053 assets/create/blockstates/mechanical_drill.json
0fb175e5260ec60e130e589d682a4d3301d7364e assets/create/blockstates/mechanical_harvester.json
f199f57510befeb2a583126bc16392e49a70dc7f assets/create/blockstates/mechanical_harvester.json
d9afcfa27c42df5fd54a7b783acb0eb45ddf5aa5 assets/create/blockstates/mechanical_mixer.json
da612a05f94dc19e07e250efc35a7b2839d2ee76 assets/create/blockstates/mechanical_piston.json
94ec340a50b2406f833735f7501a1840c692e32a assets/create/blockstates/mechanical_piston_head.json
debef0f5dde74103aaf4422de4bc90e4099b0c47 assets/create/blockstates/mechanical_plough.json
cd13e5327f1adaf9ab2bfc511ead05b2799fdfb3 assets/create/blockstates/mechanical_plough.json
92269fe66d7b83095a2e04e121af0be792f55dd6 assets/create/blockstates/mechanical_press.json
b7c4a0ff0c6f16e14d71fc0fb7fc66d032b65cf3 assets/create/blockstates/mechanical_pump.json
29ec1a3ec9b158b954f9ca126eaac89cee96cf84 assets/create/blockstates/mechanical_roller.json
264d72320ee0f1e014319f7d99dcc1fa953a4ad4 assets/create/blockstates/mechanical_saw.json
94bbcb7e622471dbf418d78f9200ad321c7168de assets/create/blockstates/metal_bracket.json
c253a827d9f0b0e29f67dfd19d65b259d3d4f045 assets/create/blockstates/metal_girder.json
@ -529,8 +520,7 @@ c9bf881ea71aa274b2803142456f1bbed9539076 assets/create/blockstates/veridium.json
c4db76b9d36cfb098df0d158cb6f8b82768ebe14 assets/create/blockstates/vertical_framed_glass_pane.json
3a5da54d9763e9512cfaa47b25226b79738b25f3 assets/create/blockstates/warped_window.json
19ef7a16c82f07d304fb60d121845185d189aecf assets/create/blockstates/warped_window_pane.json
638109f42fe1da576c8c832a79676065d54b1ee5 assets/create/blockstates/water_wheel.json
f4d185b9eb086e5024a9818bad57d524267d6e13 assets/create/blockstates/water_wheel_structure.json
d31fce8315c8715521d66b5dcc166c84e949dd1d assets/create/blockstates/water_wheel.json
97a8f4cf45776b1fb5249fe1a9314b5c615fb130 assets/create/blockstates/waxed_copper_shingle_slab.json
d31a8ad9ffa09cbabfb284d44c9c44d036072083 assets/create/blockstates/waxed_copper_shingle_stairs.json
e7be350dd2fd80357c56a0fbad3e000818b822c9 assets/create/blockstates/waxed_copper_shingles.json
@ -576,8 +566,8 @@ bf2b0310500213ff853c748c236eb5d01f61658e assets/create/blockstates/yellow_toolbo
5616dda664dd106d576848124fc0fc1de18d0fd3 assets/create/blockstates/yellow_valve_handle.json
7f39521b211441f5c3e06d60c5978cebe16cacfb assets/create/blockstates/zinc_block.json
b7181bcd8182b2f17088e5aa881f374c9c65470c assets/create/blockstates/zinc_ore.json
30815cc68ddf59924be78b1c37a0e374fafe552a assets/create/lang/en_ud.json
c6c72491c2586f70e72d7510b230e7307a4d7c99 assets/create/lang/en_us.json
f1bedeb51c35e70a2247178634e61ea637a6622e assets/create/lang/en_ud.json
59bd0d1e0f74f1dbfd2443b3e6cb8c683b57827a assets/create/lang/en_us.json
487a511a01b2a4531fb672f917922312db78f958 assets/create/models/block/acacia_window.json
b48060cba1a382f373a05bf0039054053eccf076 assets/create/models/block/acacia_window_pane_noside.json
3066db1bf03cffa1a9c7fbacf47ae586632f4eb3 assets/create/models/block/acacia_window_pane_noside_alt.json
@ -594,17 +584,14 @@ c3fdfa0ef84a598a17b2194fd0ea56fb323441d6 assets/create/models/block/adjustable_c
11c034a7689e3bc96cf54f67fd93bc3839ae19e9 assets/create/models/block/adjustable_chain_gearshift_middle_vertical_powered.json
221b65e4fed640dc77f8ec5fee300f2a199d05b1 assets/create/models/block/adjustable_chain_gearshift_single.json
ef644b33e136692c19cf8e79fcd28431b40dbb62 assets/create/models/block/adjustable_chain_gearshift_single_powered.json
647aa88fe7f74048b06e61dd092a7ce167f6e7bc assets/create/models/block/andesite_alloy_block.json
953daa66d3befd33edfb62421c01330ff9ecf441 assets/create/models/block/andesite_belt_funnel_extended_powered.json
0e0b6fffad506f7bb9f212becb69b04fdb773372 assets/create/models/block/andesite_belt_funnel_extended_unpowered.json
5be49f276346a4908366426329319366d98c0877 assets/create/models/block/andesite_belt_funnel_pulling_powered.json
3078958b74af612dbb1a5bf18b92c190d63524d6 assets/create/models/block/andesite_belt_funnel_pulling_unpowered.json
eddf206f5fffbf9446461538da9fea70f5d22f0e assets/create/models/block/andesite_belt_funnel_pushing_powered.json
31784901768ebb9322a101710c5b6c16e7185271 assets/create/models/block/andesite_belt_funnel_pushing_unpowered.json
574ece0c5d1877a07e46f0d86add876bf002541f assets/create/models/block/andesite_belt_funnel_retracted_powered.json
2ea98218be00eea0f8b58072f970b4a2d096306d assets/create/models/block/andesite_belt_funnel_retracted_unpowered.json
8d53939d0e5fbeaace7800ac055719fd24b8314f assets/create/models/block/andesite_cap.json
d497453840a05b0b958890676b819215f3a118b3 assets/create/models/block/andesite_cap_alt.json
10832d276445d8a5f94413de1979349db1364ec4 assets/create/models/block/andesite_belt_funnel_extended.json
d01611179d3ed6c013f4f649127239772cbdeba3 assets/create/models/block/andesite_belt_funnel_extended_powered.json
c862af2b37ccfd0123e9e96a5400be82033bbdd3 assets/create/models/block/andesite_belt_funnel_pulling.json
ed52e27fd7d645c25dc9dc58a44f29be12cb6d5e assets/create/models/block/andesite_belt_funnel_pulling_powered.json
884aaf754de0bfd51690aab6e01f775419728cf7 assets/create/models/block/andesite_belt_funnel_pushing.json
3c8ed64100de95994580a8e6e24c7b72f2332081 assets/create/models/block/andesite_belt_funnel_pushing_powered.json
7b1888eec72c04677a3dfb709b04ad10d08d74d0 assets/create/models/block/andesite_belt_funnel_retracted.json
240230f29d092505d47c83ae59f5c908e4bf4932 assets/create/models/block/andesite_belt_funnel_retracted_powered.json
4e44ccdc5e396c4380a7e59408db50553fa25226 assets/create/models/block/andesite_casing.json
762509cfb8602c6d0d3f959c08ad4934c2b5d8fa assets/create/models/block/andesite_encased_cogwheel.json
314489582d1cde98bc5e4fd4d2f0c9ab3cb731d3 assets/create/models/block/andesite_encased_cogwheel_bottom.json
@ -614,23 +601,22 @@ c8f215c191f46ff1ea6f098ab32c7d27d04cb017 assets/create/models/block/andesite_enc
f8f131a53664faa5bd84b61e83d62ed5b367bf1d assets/create/models/block/andesite_encased_large_cogwheel_bottom.json
77b3bbcb47e83f985d68b0ed0344e9f79999e797 assets/create/models/block/andesite_encased_large_cogwheel_top.json
01189fb179863ce1ef524bd5ddd5b4bebd5bbc6b assets/create/models/block/andesite_encased_large_cogwheel_top_bottom.json
a51ef8eb258251ecd4313d6997ce607b79a23850 assets/create/models/block/andesite_funnel_horizontal_pull_powered.json
fd19670a4504617fcd0ee0a1fb6ebeca9b30cc82 assets/create/models/block/andesite_funnel_horizontal_pull_unpowered.json
aa22be9799a91810fa0068e525dd6961d7af4900 assets/create/models/block/andesite_funnel_horizontal_push_powered.json
5ca7cfe29534b2839b2cefd6ab1047c74f9af079 assets/create/models/block/andesite_funnel_horizontal_push_unpowered.json
f2d6d85ad3e0899855d2c6658484e33ea9d5e2e0 assets/create/models/block/andesite_funnel_vertical_filterless_pull_powered.json
afa3669c0d80b4eccd839fa08a3c3e884f5dd1f6 assets/create/models/block/andesite_funnel_vertical_filterless_pull_unpowered.json
eeb2637590e8af1342c5494dea7faab0490f2f3e assets/create/models/block/andesite_funnel_vertical_filterless_push_powered.json
2c0e1bb2edca1c0315e4b989d1ae58b8fe681d05 assets/create/models/block/andesite_funnel_vertical_filterless_push_unpowered.json
8d4e4a7c6ad6d45c7aa7ca3105a025511571ff26 assets/create/models/block/andesite_funnel_horizontal_pull.json
9841d6a09a09bf4d5d6a39bdc4904d86b3a825f8 assets/create/models/block/andesite_funnel_horizontal_pull_powered.json
86d5df6e365d9b2e9682f0839f61058360828ba2 assets/create/models/block/andesite_funnel_horizontal_push.json
50af1ff6ce9af162d4e438f21952c7215608dc8e assets/create/models/block/andesite_funnel_horizontal_push_powered.json
75c914bf9448e25fd01d597de48375a9782bef36 assets/create/models/block/andesite_funnel_vertical_filterless_pull.json
4d70a221809f5bc598a0a0e98bd152e9ab7a2f7f assets/create/models/block/andesite_funnel_vertical_filterless_pull_powered.json
a41c7351513a9514dfdc0fc552b646b1d715c977 assets/create/models/block/andesite_funnel_vertical_filterless_push.json
e7931f28887baadd52ac988fc8eeeb84ee6f0d27 assets/create/models/block/andesite_funnel_vertical_filterless_push_powered.json
ee665cf464ead6135de3f60c7e2ac475af6496d7 assets/create/models/block/andesite_ladder.json
882871d4cd7b4925f300c09d00ba58785b27119e assets/create/models/block/andesite_pillar.json
587491f19767bd682bbef00eaa890d4b8a320b7a assets/create/models/block/andesite_pillar_horizontal.json
3d5bce20c58e7503b3868edac97f32556ccd1b6f assets/create/models/block/andesite_post.json
722e1e40ca4153887d57c9c90d70d94dd87a0bc1 assets/create/models/block/andesite_post_ends.json
23dc81d6e683b0fd8c1dedcfdb8a4aa04f99b3a0 assets/create/models/block/andesite_scaffolding.json
9634056c616296a8106350dc40222e904688585d assets/create/models/block/andesite_scaffolding_horizontal.json
677d75755bc1fba56823292b2abe03a495ba2910 assets/create/models/block/andesite_side.json
419288e05242def13d58c1a8174673c33732b4a5 assets/create/models/block/andesite_side_alt.json
2294f74b5c30430de89a345af60f6669c975f33a assets/create/models/block/andesite_tunnel/cross.json
17f860947f51e84a3f9b32b10cdf61f863db3afc assets/create/models/block/andesite_tunnel/straight.json
e74aa39f8142293c202e57dbd92e8660818b18b5 assets/create/models/block/andesite_tunnel/t_left.json
c93978d636fe70d456a6e1914b65527cbc18544c assets/create/models/block/andesite_tunnel/t_right.json
2a86780c6825edce8fbdaa118a267fc09ce410b0 assets/create/models/block/andesite_tunnel/window.json
7b2e3b7e9d72286b202bb38ab6e4d69465365d47 assets/create/models/block/asurine.json
a9167990e3f894f92a9de24c8b77d040b1c1ff0a assets/create/models/block/asurine_pillar.json
e40c3a7e6f7b895770f544d79536c744d18c462f assets/create/models/block/asurine_pillar_horizontal.json
@ -662,17 +648,15 @@ c86a455b8e85ef190261718726b344cf15ba1e4f assets/create/models/block/bracket/shaf
8fa9ce896412af894d7c431a50104445d91b1d4d assets/create/models/block/bracket/shaft/ground_wooden.json
3956168840aca9425d3bf240650406c1dbc8ea66 assets/create/models/block/bracket/shaft/wall_metal.json
7aaa2fbdb618e8aab7e0da19a5393e1eaa608623 assets/create/models/block/bracket/shaft/wall_wooden.json
18048eac6c45e30c47cc7fc964b0986cd033bc00 assets/create/models/block/brass_belt_funnel_extended_powered.json
7870163874d8d2e29e9bed3fcaf5be715d0de541 assets/create/models/block/brass_belt_funnel_extended_unpowered.json
e4894b8cb9dda7aa4b9d035ae16f705459ddf14c assets/create/models/block/brass_belt_funnel_pulling_powered.json
8d86c2f3ddd51dc6b15d1e4ce115f0d7b1e28dda assets/create/models/block/brass_belt_funnel_pulling_unpowered.json
f0a9b05c69e67aa61b88f6db5d818ae191b3aad5 assets/create/models/block/brass_belt_funnel_pushing_powered.json
710f4903e7022761c43f7def240d5aad98389871 assets/create/models/block/brass_belt_funnel_pushing_unpowered.json
e0958b94c40e4aabbcbabd70be8a368eb877dcf9 assets/create/models/block/brass_belt_funnel_retracted_powered.json
5715303e539e6005a347480e52db2c7e6676c716 assets/create/models/block/brass_belt_funnel_retracted_unpowered.json
2b1ca994d2feec8321fdb0388028c20d40326eb7 assets/create/models/block/brass_block.json
a094db3862d765e185c4849ce0a50967ee95d7c1 assets/create/models/block/brass_cap.json
2dbb68d4917cac90fd6fe05abf5f7432288fdbed assets/create/models/block/brass_cap_alt.json
3fac6b1da6a81fc44a1ffe1e13dc6cfe37c3b738 assets/create/models/block/brass_belt_funnel_extended.json
2d10825bfd94419d5dbb4e60187127c4a1ce1526 assets/create/models/block/brass_belt_funnel_extended_powered.json
dfc6250e28e12ff193a45891978ec50c406fc0c2 assets/create/models/block/brass_belt_funnel_pulling.json
5ff7e01c5b65eb210a054556068d75426b547d9b assets/create/models/block/brass_belt_funnel_pulling_powered.json
5409325494780afe32e6e30377314e2992ca4aa5 assets/create/models/block/brass_belt_funnel_pushing.json
e981727fd71e32ea2ecb8e057dfe123f1b940101 assets/create/models/block/brass_belt_funnel_pushing_powered.json
97410a12b7c1461f88fb633f26ff566a0636b627 assets/create/models/block/brass_belt_funnel_retracted.json
bc23a91f300e46761bb14c597fad39c3d414e84d assets/create/models/block/brass_belt_funnel_retracted_powered.json
5adb8b446817eee3a31971d708320c7104d6bbd8 assets/create/models/block/brass_block.json
2e67c147d7c69aabd9ab9f7aa80f60671d5a03aa assets/create/models/block/brass_casing.json
8cb0039684377c27a7fe20bdcacf24f871221478 assets/create/models/block/brass_encased_cogwheel.json
c735917634c87b3d289bd912c7ceb465a3cc65b6 assets/create/models/block/brass_encased_cogwheel_bottom.json
@ -682,21 +666,20 @@ c2199a633597a73a1c2d508e5dfe0a7589b02329 assets/create/models/block/brass_encase
ed150a9e18889217b7f010412e4317af04af7dc1 assets/create/models/block/brass_encased_large_cogwheel_bottom.json
bb4155627c1f189e2e3bc07822d227bb0fc64bc4 assets/create/models/block/brass_encased_large_cogwheel_top.json
421cbc9bcb6511c66ff7122d1800bcd8ab866b2b assets/create/models/block/brass_encased_large_cogwheel_top_bottom.json
68f57bccd8a7ec0a997ab65aab74103338b0ade0 assets/create/models/block/brass_funnel_horizontal_pull_powered.json
327643126b6b4a93523354ac70b0148d36176c75 assets/create/models/block/brass_funnel_horizontal_pull_unpowered.json
49c2cf87fb273d7e557cfde908e319f7810e333d assets/create/models/block/brass_funnel_horizontal_push_powered.json
f5bc8543b6b6cddeb455a1c20500240de9d837ac assets/create/models/block/brass_funnel_horizontal_push_unpowered.json
c76668b6b61a3f81a08a1eadaa34fa8bfe68f912 assets/create/models/block/brass_funnel_vertical_pull_powered.json
33c07af5f61f89d781037a5841335e4783392fde assets/create/models/block/brass_funnel_vertical_pull_unpowered.json
2d78db12acd90364658b36e8fe7dee7f24ea361b assets/create/models/block/brass_funnel_vertical_push_powered.json
aa81eeb9771e59173ecf635f7c5334ac64c83b6d assets/create/models/block/brass_funnel_vertical_push_unpowered.json
f7fd1f49857eca94e4135e65c85127510d666e4f assets/create/models/block/brass_funnel_horizontal_pull.json
45a23298ad03fd3b5dc2757dcd7edc18b8cce222 assets/create/models/block/brass_funnel_horizontal_pull_powered.json
a9fc7210d44b47202438668f11b31099e82c9ebd assets/create/models/block/brass_funnel_horizontal_push.json
4049bf503ec2ee22412c59e05299de20319b0dc6 assets/create/models/block/brass_funnel_horizontal_push_powered.json
320e377a4380ac637bff2e0535f229c52d886437 assets/create/models/block/brass_funnel_vertical_pull.json
28c2f8ca6403f98b82e3a0eadb608a41490cc96f assets/create/models/block/brass_funnel_vertical_pull_powered.json
c4c46d47854c9a6cf8f410006a35bbc8e599f0d5 assets/create/models/block/brass_funnel_vertical_push.json
fd6f6607a4742fa87dfe1768927a29dc4975ce7a assets/create/models/block/brass_funnel_vertical_push_powered.json
5620cf6b033dbfb3c43d03ddad18c432eb821997 assets/create/models/block/brass_ladder.json
74d090cda85c793c285c028537c396a074366b9f assets/create/models/block/brass_post.json
7e49c7ecf886d031f33a6fe748200e07099d7c9f assets/create/models/block/brass_post_ends.json
de296beb1a8f1d51f2533e166800c65d69a8b091 assets/create/models/block/brass_scaffolding.json
a276726447e4c22a259d224f8124ea863cb36b3c assets/create/models/block/brass_scaffolding_horizontal.json
9ad24eae18506bf66c893fcb99ca15c9f50b7e58 assets/create/models/block/brass_side.json
63c93da138d7787b415cb5459975cc2a220e2c1d assets/create/models/block/brass_side_alt.json
520087db8d479c66f85f3483af813fb668f27503 assets/create/models/block/brass_tunnel/cross.json
347ed67bf3426e323354e2d959fc9563dc7eeecd assets/create/models/block/brass_tunnel/straight.json
a959e03ca339badb49fe58ba53d86a84352e91f3 assets/create/models/block/brass_tunnel/t_left.json
0585fbe58da3a8ed0dc98cc7ed79ac067312078d assets/create/models/block/brass_tunnel/t_right.json
a0612a633756433e1b37ddc6d290aa1fc07839ef assets/create/models/block/brass_tunnel/window.json
71cd22dc2d847d317f19afb4b21802fbf5347e0b assets/create/models/block/brown_nixie_tube.json
8ab097caaa0db0915ae9254f7d65092d9171bc60 assets/create/models/block/brown_sail.json
4eed0ad902f5e84f2b6c160f3283e8028640e77d assets/create/models/block/brown_seat.json
@ -706,22 +689,14 @@ a276726447e4c22a259d224f8124ea863cb36b3c assets/create/models/block/brass_scaffo
c4d1e1b6e195c0b71c0b96546978cd24c4a4bfc4 assets/create/models/block/calcite_pillar_horizontal.json
4156227e18c0896ce83f260f71b939abbbf4f01e assets/create/models/block/chocolate.json
30fe120af3cb32faf0729df4d2cdf868f804be17 assets/create/models/block/clockwork_bearing.json
4db08101a5d03303506e89adc9ff394ed26cd2e6 assets/create/models/block/copper_cap.json
06447f3c1e3f6d53d3887cedc20c322b146bdb1f assets/create/models/block/copper_cap_alt.json
1f01a4b6608f75145734b60ddf4a33ce318425ff assets/create/models/block/copper_casing.json
c53dacdeb2e5c51de0706d87ad2d2c02a0d004b0 assets/create/models/block/copper_ladder.json
6a6ac93ba3ba00319d0c22c858e414a9bdfcd748 assets/create/models/block/copper_post.json
ceb03be484c0cf8e754ea39faab0834d820a5c6b assets/create/models/block/copper_post_ends.json
4d35570ae6b228528656f95faebb227dfbad1a1e assets/create/models/block/copper_scaffolding.json
fa60214501fd2e5007672ec3af5db1f20878f5b5 assets/create/models/block/copper_scaffolding_horizontal.json
9967651b9323174836a3179f088fa1dd7518270d assets/create/models/block/copper_shingle_slab.json
a8b28ae828c1e092bf499dd1fbeb9b19c40e3206 assets/create/models/block/copper_shingle_slab_top.json
e577cb469c8adfb3fed81232419393611665a5f6 assets/create/models/block/copper_shingle_stairs.json
ed9e72e163883a784cee42157701955f30831fbf assets/create/models/block/copper_shingle_stairs_inner.json
8ae100e7aa52c0e5baa3685974258e4e070242bb assets/create/models/block/copper_shingle_stairs_outer.json
d4cb771acc143cb4361270db0025ca92864434cd assets/create/models/block/copper_shingles.json
1169b17185f0a564f6e08a71617cec62687d2487 assets/create/models/block/copper_side.json
667d98fdb2dc43067bc2591f0ae26e4d17c758ff assets/create/models/block/copper_side_alt.json
8a10c93a3fc2d7bc7019a47a9fa89711bdd9232e assets/create/models/block/copper_tile_slab.json
92c7cb2584fe0b1071eeafca2abb3f4d9143c330 assets/create/models/block/copper_tile_slab_top.json
5ae6a5c2d7ab022a7df376d54c06316a9da77314 assets/create/models/block/copper_tile_stairs.json
@ -1121,7 +1096,6 @@ d13df8a5920c5778d98081fb0e97f045e2fd46a2 assets/create/models/block/horizontal_f
a5938ddd48109f067a19a90a0f9abab655c18821 assets/create/models/block/horizontal_framed_glass_pane_post.json
41645919ece236df5804a5a73ef682720194de34 assets/create/models/block/horizontal_framed_glass_pane_side.json
8bc0abaabdc62d0c27730dba7eb6da54607b7e96 assets/create/models/block/horizontal_framed_glass_pane_side_alt.json
07c1e1bcd87766cf324ac11ce1488856d1db86c3 assets/create/models/block/industrial_iron_block.json
35253c91ed72c7c2ce981c384d334c1113851469 assets/create/models/block/jungle_window.json
65da656d412d973865f50ab7f02e278fe5398bea assets/create/models/block/jungle_window_pane_noside.json
9f4144df2e6b35c1fad04e594be5adb3b107bdb8 assets/create/models/block/jungle_window_pane_noside_alt.json
@ -1550,16 +1524,6 @@ d257b024117a6003196c1feb85e759a3e1c180f7 assets/create/models/block/tiled_glass_
6b1727111d9178162598b4ef7106da807d590bf0 assets/create/models/block/tiled_glass_pane_side_alt.json
6b44ab14b227f3c46ee99eecfe47a86c9fb0865c assets/create/models/block/tuff_pillar.json
f0faeee9e124a25280fb58bd66045cfb2758b42e assets/create/models/block/tuff_pillar_horizontal.json
adfd211b3eb33497fad7e58de0d4784b8ce698b1 assets/create/models/block/tunnel/andesite_tunnel/cross.json
8765e95adeed03fa8203ca7a9f221392a6f038be assets/create/models/block/tunnel/andesite_tunnel/straight.json
429cd29a4c4781cf09e11c4e90451bdc61d455f6 assets/create/models/block/tunnel/andesite_tunnel/t_left.json
9c679b1033abfe4c44df69eeef60eb44efff47a2 assets/create/models/block/tunnel/andesite_tunnel/t_right.json
7cb18c3795d1481b588ce9d5dd013f45902aac47 assets/create/models/block/tunnel/andesite_tunnel/window.json
6eca538d20ccbc2974ed7c6f01dc6227d33ebc1d assets/create/models/block/tunnel/brass_tunnel/cross.json
ec2bf287791e891f85b71f97ee196002f9b03bf2 assets/create/models/block/tunnel/brass_tunnel/straight.json
37d15648b9358cb8bd4a3f20df40c36ddc07efd7 assets/create/models/block/tunnel/brass_tunnel/t_left.json
2f75336b25f5f0a008878488599e59b3e3504174 assets/create/models/block/tunnel/brass_tunnel/t_right.json
8ac0130f727696786141d7d61261072739c7f72e assets/create/models/block/tunnel/brass_tunnel/window.json
dee64127644e7b09168be26b6665389885476e05 assets/create/models/block/veridium.json
ebfad96e85ac6107642eaaf48b57315b268355ff assets/create/models/block/veridium_pillar.json
c49bb21ef60ff10540952271c863415b4ad07aa0 assets/create/models/block/veridium_pillar_horizontal.json
@ -1652,17 +1616,14 @@ c695dab3964186a857767b2b4975aebffa86dcf9 assets/create/models/item/acacia_window
564f6245f92ec48a733e34d91b96b1beebbaf44a assets/create/models/item/adjustable_chain_gearshift.json
e7759d9b3cd64d2719a58dc35fc75ca65b9e14fa assets/create/models/item/analog_lever.json
2e90c7abfcad12ca656ae253d834fbb799e15277 assets/create/models/item/andesite_alloy.json
2e7cf267efb66404721ac8bf08802de0eb134159 assets/create/models/item/andesite_alloy_block.json
946756a1a498ccd2e61b33ef317c5ec9e30afebf assets/create/models/item/andesite_bars.json
174c9705d25f149052835fdcf7c85626afead90b assets/create/models/item/andesite_casing.json
420020284d01c72a7fb3387750fe1dd2dcfb9550 assets/create/models/item/andesite_encased_cogwheel.json
6e246e91b4ebffd5c45311057feb5d26d1cb8aec assets/create/models/item/andesite_encased_large_cogwheel.json
bc6e7469744604e578200ea87690e4dd3b25e447 assets/create/models/item/andesite_encased_shaft.json
105a9946b9e4d5e949f6d557cfde750227463bff assets/create/models/item/andesite_funnel.json
a3866ea9f44e80b64989f2b5f8a9f344da959c87 assets/create/models/item/andesite_funnel.json
4c9232a6249ad1ef51a7978a8e642a8c88dda0ab assets/create/models/item/andesite_ladder.json
75b8b00c2418b9660d35a7fabd0774925cf1c02f assets/create/models/item/andesite_pillar.json
5d4616aa0ad5192f8c4029f327f1f79dd04e1e81 assets/create/models/item/andesite_scaffolding.json
473be56fe1f44809ffecbb3eb86107af3ca7a569 assets/create/models/item/andesite_tunnel.json
795541cf7205d90531a23cd5b388f93a03bbf925 assets/create/models/item/andesite_tunnel.json
cc6471e712a6db7856e62a99b8ef7e378480fa27 assets/create/models/item/asurine.json
840a34731a823e185a180bef029dd16ee3f78541 assets/create/models/item/asurine_pillar.json
cf9e35bfea0b0a324e1c6384990425b3d359792c assets/create/models/item/bar_of_chocolate.json
@ -1679,20 +1640,18 @@ d537fffaede521efa525fb2a7f9863fe6a80054e assets/create/models/item/birch_window_
0e1977585128fc0ecef640f72e5fc5e9fb47ef92 assets/create/models/item/blue_seat.json
c637be1586260cf91e6da57c71c33f4515008227 assets/create/models/item/blue_toolbox.json
bec96ebf3369d3cffa9bb1b8bf9f2a5cd5d0ef96 assets/create/models/item/blue_valve_handle.json
5afa91abed387b3dfa39c39c7feae5f8f02a4bd9 assets/create/models/item/brass_bars.json
17d340c3678bd24cb085ba49490b2b4cb341a9e7 assets/create/models/item/brass_block.json
f5a18f4279c2e845a5967b1c2f9e807c2bb77afb assets/create/models/item/brass_casing.json
099179a466a2f370dd2c4fea0d841517fa3a558b assets/create/models/item/brass_encased_cogwheel.json
6e60b5939747835b2247cbc4907d633b017abc79 assets/create/models/item/brass_encased_large_cogwheel.json
c723011e09203821b6b59cff9de22454c5e4395a assets/create/models/item/brass_encased_shaft.json
8de90ceb9997f61efc544304fcd919a54db47d41 assets/create/models/item/brass_funnel.json
12781f22d9b91df903d38bc55c4fe9f75dba8867 assets/create/models/item/brass_funnel.json
965f3f992fde899719506fd584f3fbbbf69af93c assets/create/models/item/brass_hand.json
d5e8b577aee56671e117a4a2ac93e58680b51949 assets/create/models/item/brass_ingot.json
1f93ec11bd28a3f063f27e8c53fc45d027218560 assets/create/models/item/brass_ladder.json
44565b9b2c227e99e336357e5caa588438e7076b assets/create/models/item/brass_nugget.json
713ca067a3fd88c28e78ea8c9c8442b2f85ab812 assets/create/models/item/brass_scaffolding.json
f7aca6aff65e1de269a99cf2a280d9841b7a0076 assets/create/models/item/brass_sheet.json
d8ee5b3cc82e5465f5c7ada88cfd444c62e3c84d assets/create/models/item/brass_tunnel.json
427bef12405e2a99fbf49e27ea5944add244252a assets/create/models/item/brass_tunnel.json
24df6f8391d8ba09cef46e69d65d32ea770745cd assets/create/models/item/brown_seat.json
9d66f8bdc2db7cacf52168d5a267d5f52a2b351c assets/create/models/item/brown_toolbox.json
54211d3bdbeba2ea4dbaed43daa740ae3331640f assets/create/models/item/brown_valve_handle.json
@ -1713,13 +1672,11 @@ f5f1ad973341f8bebc474d5e65ff877ac6303b0d assets/create/models/item/contraption_c
9a93b3ccef02cd0abd8106edec954dc0f2269229 assets/create/models/item/controls.json
10397036fc0bb1e18a767cfd7b19b10d805a83fe assets/create/models/item/copper_backtank.json
3652f8f7b454940050f090ab32d38e04b93e14f8 assets/create/models/item/copper_backtank_placeable.json
bd476beac53d01a51d9690e6069de4033f02d6b8 assets/create/models/item/copper_bars.json
759bcb5fe7dfdd628716f9b4ff19a5ab00393381 assets/create/models/item/copper_casing.json
16182c4c32b11b370cf5b1116250cf3dda838954 assets/create/models/item/copper_diving_boots.json
dc517e70cee9c5d74edfedd49ac43a67fe258c1b assets/create/models/item/copper_diving_helmet.json
599845f2382da5b43a3c610f6ed7a87c032e1c6a assets/create/models/item/copper_ladder.json
751324b03f657f4166460eb10a64dae47cb97bd4 assets/create/models/item/copper_nugget.json
b22b214f534b9f7308e958487e2d3270d4da16e4 assets/create/models/item/copper_scaffolding.json
177dafb51d70c55ec62036332868efed4e01f353 assets/create/models/item/copper_sheet.json
b4f378b2552ab0893a8a1a8abb71f2fcda658132 assets/create/models/item/copper_shingle_slab.json
1e67f3b28e9488091086b2ff46ae612f6c68af0e assets/create/models/item/copper_shingle_stairs.json
@ -1753,7 +1710,7 @@ cecee6daf2619dcf035c7aea5fff1bd892f6ff06 assets/create/models/item/crushed_silve
a8d3f330d312f82b0de59940581910090b2bd012 assets/create/models/item/crushed_tin_ore.json
b359064405d189e2802969715cd5f682ddbf0bb1 assets/create/models/item/crushed_uranium_ore.json
2bb791db62dce6bf2e2227f9b607c131828471fd assets/create/models/item/crushed_zinc_ore.json
f9a158bd5bbbf60310e8f3d4f10911e8baf03579 assets/create/models/item/crushing_wheel.json
823c91f63565db54ec3944a1e90e7aee18e41062 assets/create/models/item/crushing_wheel.json
dae5cffa4e1263d6a113469f79fba8695fa8232a assets/create/models/item/cuckoo_clock.json
120cb6f4fc6b28d86117dbe059b990c1303c46ee assets/create/models/item/cut_andesite.json
9c94151d18e0201e1e1967713f2ab86ebc9c647b assets/create/models/item/cut_andesite_brick_slab.json
@ -1928,14 +1885,12 @@ f0e3b2b8a553b6e61746c922c27302dabfff71b6 assets/create/models/item/horizontal_fr
ff92f6a9dfb73a6ee1eaaed3279c89390ff04a80 assets/create/models/item/hose_pulley.json
153a185852af79654f0fb216c4b1b8e69c85ee8a assets/create/models/item/incomplete_precision_mechanism.json
d4883a5c777abb6c5235563eadb70e2b1b3de17b assets/create/models/item/incomplete_track.json
0503eda6f4c3fa320a2d59ac4a454a6f5e9cd787 assets/create/models/item/industrial_iron_block.json
9d605ce0da83a73b535bce45c107e604364e2b20 assets/create/models/item/iron_sheet.json
52e435014cb03e93411666c4799ebff206e55fc9 assets/create/models/item/item_drain.json
76ab46c9b64faf5e94391579eec5115360dff73d assets/create/models/item/item_vault.json
83fa8699318e51f838b483b40b3e897c34ed53d1 assets/create/models/item/jungle_window.json
766323f6026c3505a75db2dee2996d342370d9c2 assets/create/models/item/jungle_window_pane.json
bcaaf60d9a853cce90169dabcb36d29a3ce19e18 assets/create/models/item/large_cogwheel.json
7418fb83e9b4ad6cab8e0a28aff7f615fbfb20b4 assets/create/models/item/large_water_wheel.json
281e2b055c6eb6994ca306c8957fc80a98fb5473 assets/create/models/item/layered_andesite.json
ad814f2eef3415c44e1df73a84011fbe801a0de3 assets/create/models/item/layered_asurine.json
d188923db1e37aeac3b24ee2e6f0a4a13a794da9 assets/create/models/item/layered_calcite.json
@ -1976,6 +1931,7 @@ f8d0d4b2a890ea7a69ab0c390947b48fe0478d3f assets/create/models/item/mechanical_pi
726ae61699dc379a4f535c1be3ec2672a2f03583 assets/create/models/item/mechanical_plough.json
6c2acb80e53256fbb85f76851f335f9248ace6da assets/create/models/item/mechanical_press.json
4e363477e3e8059dd7b2bad04046521b31923d1b assets/create/models/item/mechanical_pump.json
2d7d314661e39f027c118cf14ae2f4acf213b9be assets/create/models/item/mechanical_roller.json
3fc1fcb2016d2782c3667c21575423122b66705a assets/create/models/item/mechanical_saw.json
3afa723a8ba4160a4bd8778a56e1880e7ff53ed9 assets/create/models/item/metal_bracket.json
56494f6d8743241836f7e68122ad9cc83f77658a assets/create/models/item/metal_girder.json
@ -2206,7 +2162,7 @@ fb24881c4e92bbb7ffa54a71e0af6b1c66d84829 assets/create/models/item/turntable.jso
2d4a31321cc13f62f5fd73aabdc5fd97e635bfbc assets/create/models/item/wand_of_symmetry.json
89493fa0691453d6c604e3ed9ae077fe43648d18 assets/create/models/item/warped_window.json
5f169d526b4697c85e6d113be4ff81a2b45b6e6a assets/create/models/item/warped_window_pane.json
fc03f409357f75af210d3a77df588224e00a0af0 assets/create/models/item/water_wheel.json
ae20383b0b0806431d0fdd8ffdd16fe2b0cc61ad assets/create/models/item/water_wheel.json
d4be2b3cc812b5a692162c1be03744c151bdfe2d assets/create/models/item/waxed_copper_shingle_slab.json
5133884393aeb3d812d437983e0ddee84ad82c71 assets/create/models/item/waxed_copper_shingle_stairs.json
69f7261ed8967a728298ca89b1018704cf4c01d4 assets/create/models/item/waxed_copper_shingles.json
@ -2349,18 +2305,11 @@ cbe6b6d0eb188a8c0600b54cee860116d305e905 data/create/advancements/recipes/buildi
34ceb3033f5f41a5fdffeea0a3adead36748f65a data/create/advancements/recipes/building_blocks/smelting/nickel_ingot_compat_thermal.json
edb22e0bb018cf00e51f37d912939207c4bf5ac5 data/create/advancements/recipes/building_blocks/smelting/silver_ingot_compat_thermal.json
f10041d864bfb1e6f017e442ae85ee9503b3f5a4 data/create/advancements/recipes/building_blocks/smelting/tin_ingot_compat_thermal.json
d7d55d04aba6492690df1c68b75d457b0b537d2f data/create/advancements/recipes/create.base/andesite_bars_from_andesite_alloy_stonecutting.json
60608f8fff394857b8b7d3b1478b847fd20160f4 data/create/advancements/recipes/create.base/andesite_ladder_from_andesite_alloy_stonecutting.json
bc9aa565038013430adacea933fc32443e7fcdc8 data/create/advancements/recipes/create.base/andesite_scaffolding_from_andesite_alloy_stonecutting.json
ba80332510acab3f60f30d8b802ee2d450fd51b9 data/create/advancements/recipes/create.base/blasting/zinc_ingot_from_crushed.json
4bb60ef5e186f12a9d52e61319db8c78300c64ab data/create/advancements/recipes/create.base/blasting/zinc_ingot_from_ore.json
00ff89f208cb9023d7a2657c43d267e21755fb2e data/create/advancements/recipes/create.base/blasting/zinc_ingot_from_raw_ore.json
ac987d22204c01642cbda1c8e3d81604741ff777 data/create/advancements/recipes/create.base/brass_bars_from_plates_brass_stonecutting.json
13ce2dba955de3b6b943fa406e3dde6863093820 data/create/advancements/recipes/create.base/brass_ladder_from_plates_brass_stonecutting.json
a039d4cb73eb870adcf0c0faa49ef89306ffc139 data/create/advancements/recipes/create.base/brass_scaffolding_from_plates_brass_stonecutting.json
d5b34cd969809370372860507c3efd3b6eac321e data/create/advancements/recipes/create.base/copper_bars_from_plates_copper_stonecutting.json
1dea56b4759da676f0edf0878ec834a4129d110b data/create/advancements/recipes/create.base/copper_ladder_from_plates_copper_stonecutting.json
9a082358daa8a0e5b91065e6fe38665f76d246b3 data/create/advancements/recipes/create.base/copper_scaffolding_from_plates_copper_stonecutting.json
19b18800dfc55508e250ebb87fbaa70510736834 data/create/advancements/recipes/create.base/copper_shingle_slab.json
0a8b2f2e35c128e470d0fd1a886b9d6ca2e99483 data/create/advancements/recipes/create.base/copper_shingle_slab_from_copper_shingles_stonecutting.json
6b066af05bef4c41a6b8fefa2cb38bcdb821eada data/create/advancements/recipes/create.base/copper_shingle_stairs.json
@ -2407,6 +2356,7 @@ bb138bedd2aec741fa54b6b52be384fdbd741249 data/create/advancements/recipes/create
a8c72e7e02fd0843d33fa4c5d43de81f29bc3aa4 data/create/advancements/recipes/create.base/crafting/curiosities/peculiar_bell.json
5a6613ff9c493c02f70b54d6dd162948002d533b data/create/advancements/recipes/create.base/crafting/kinetics/adjustable_chain_gearshift.json
1eed818673d57a9e9c28e90a2d87b97c28f85784 data/create/advancements/recipes/create.base/crafting/kinetics/analog_lever.json
0c84fb9afd00efcdbfbee8fab7894742a723ef2b data/create/advancements/recipes/create.base/crafting/kinetics/andesite_ladder.json
3e9753006da898d4569bbeabf95997e8c90847c8 data/create/advancements/recipes/create.base/crafting/kinetics/attribute_filter.json
08b21b30437a1c6e7ba61b137f17aabb6c24acab data/create/advancements/recipes/create.base/crafting/kinetics/basin.json
de5160b4c1813b62ecc0c1955085da13f1c74d88 data/create/advancements/recipes/create.base/crafting/kinetics/belt_connector.json
@ -2466,7 +2416,6 @@ a9f2c8a0b0b322741575ef833a461006ef2f0421 data/create/advancements/recipes/create
2ccfaf572456e8642a0070ea6928a082f98c63af data/create/advancements/recipes/create.base/crafting/kinetics/item_vault.json
73433a5cd400ed392796a4e543f15c42dd499fe8 data/create/advancements/recipes/create.base/crafting/kinetics/large_cogwheel.json
1c9e9888ccc51ddf76b9df0c186e74efaefb1256 data/create/advancements/recipes/create.base/crafting/kinetics/large_cogwheelfrom_little.json
5a1df5831fe5d2e2a6cbedcbc67216dd566e7fa0 data/create/advancements/recipes/create.base/crafting/kinetics/large_water_wheel.json
eb007bb079bbe6b6aaad2ca90f5af84261e3f8ea data/create/advancements/recipes/create.base/crafting/kinetics/light_blue_seat.json
571da50fbf5f2fcd3363b3dab91e7233e0ebffa0 data/create/advancements/recipes/create.base/crafting/kinetics/light_blue_seat_from_other_seat.json
ddd80e84a7d595bbb3cf405a902ebbfd4ea5263c data/create/advancements/recipes/create.base/crafting/kinetics/light_blue_valve_handle_from_other_valve_handle.json
@ -2491,6 +2440,7 @@ c32f74a21df56b67f99366fba747277c40b09935 data/create/advancements/recipes/create
ab3cb22e7cb2469c69a177ba83e29a2e1abdc3f8 data/create/advancements/recipes/create.base/crafting/kinetics/mechanical_plough.json
6b1ae84d071e8fc7a1789aaeb01a15260831fc82 data/create/advancements/recipes/create.base/crafting/kinetics/mechanical_press.json
90434eccfbcff42e8bc397881fd9d68f2dcb7ad4 data/create/advancements/recipes/create.base/crafting/kinetics/mechanical_pump.json
b0fabbe0b97cf7a56260af78cb29d21c55aafbe1 data/create/advancements/recipes/create.base/crafting/kinetics/mechanical_roller.json
40a87b7abbc22436efab546fad3910f4a945c5fc data/create/advancements/recipes/create.base/crafting/kinetics/mechanical_saw.json
ed6f472a0de659074e384d20e6c5903bda543acc data/create/advancements/recipes/create.base/crafting/kinetics/metal_bracket.json
3072592260b044257cc53be8f023909394b6cfea data/create/advancements/recipes/create.base/crafting/kinetics/metal_girder.json
@ -3432,8 +3382,6 @@ f92b20e0ae4c8808479df3553203c1b5e334cfe3 data/create/advancements/windmill.json
98f71c17409a37a584eed6cb6ee3878efebf3ef6 data/create/loot_tables/blocks/acacia_window_pane.json
c5c0b82ab3bcd7ffd1bcb65d00876aaba69363f9 data/create/loot_tables/blocks/adjustable_chain_gearshift.json
a4716789704bb30cf1c518b04c61661ba6289efa data/create/loot_tables/blocks/analog_lever.json
03eadc2a4695b505e92c1a688dc7af619fd364c0 data/create/loot_tables/blocks/andesite_alloy_block.json
bda9c999d5f4313fa1f22b3034a359f2d7947d64 data/create/loot_tables/blocks/andesite_bars.json
468759c042e8410da9230357f4b602766190df79 data/create/loot_tables/blocks/andesite_belt_funnel.json
f9b768b3b9bbddede80912f1319e7b290cd90f20 data/create/loot_tables/blocks/andesite_casing.json
982a41e1bccd9a130a2874aff995d4f7da0f0316 data/create/loot_tables/blocks/andesite_encased_cogwheel.json
@ -3442,7 +3390,6 @@ a70fcfe474ba023adc9c326218c5664fbd7b58f8 data/create/loot_tables/blocks/andesite
468759c042e8410da9230357f4b602766190df79 data/create/loot_tables/blocks/andesite_funnel.json
7587038b38c8668cdaf877951366d73ac1cfb46d data/create/loot_tables/blocks/andesite_ladder.json
e03a5c4d5ff2a171290d76d8748d1b5fe6405e4a data/create/loot_tables/blocks/andesite_pillar.json
ff34b32f062b14ac7d924de33fbaaafb273c4537 data/create/loot_tables/blocks/andesite_scaffolding.json
50c317613430a3d7b303765d8272b92cd91fccc9 data/create/loot_tables/blocks/andesite_tunnel.json
15d31b6a146f5d4e2dd0fc3062f0d60a47cb2e51 data/create/loot_tables/blocks/asurine.json
d1778ef9cc3e3e67460e02b433229e3b957d37cb data/create/loot_tables/blocks/asurine_pillar.json
@ -3461,7 +3408,6 @@ be99e48382ef8ccfb94c227c4dec7b627b4128e7 data/create/loot_tables/blocks/blue_sai
d9ac8bc87a48f7deae99440f10c361f46853951e data/create/loot_tables/blocks/blue_seat.json
0e06e0aee6b00090905b1455989ed585dc22d024 data/create/loot_tables/blocks/blue_toolbox.json
f5709ddd387ac4634244f5d002122fc4e62644e2 data/create/loot_tables/blocks/blue_valve_handle.json
4d3c7a2d56fcc46e6dd86b74f1e8c918153b4d7d data/create/loot_tables/blocks/brass_bars.json
fae7b622f27b426b1d3e6f31cd0157aff672a42d data/create/loot_tables/blocks/brass_belt_funnel.json
e8535a9acc565e8d80fa4c15f0ef6c4ffd842856 data/create/loot_tables/blocks/brass_block.json
a2d433dcfe44c9a3c1b5dd16415a2f31edbe309d data/create/loot_tables/blocks/brass_casing.json
@ -3470,7 +3416,6 @@ a70fcfe474ba023adc9c326218c5664fbd7b58f8 data/create/loot_tables/blocks/brass_en
09907573ad2602251401bc53db0e389a45d6833c data/create/loot_tables/blocks/brass_encased_shaft.json
fae7b622f27b426b1d3e6f31cd0157aff672a42d data/create/loot_tables/blocks/brass_funnel.json
b8eeab4d503cc9e43824ddd5aeeb007089780a07 data/create/loot_tables/blocks/brass_ladder.json
40a982e856eaee1b278a184eb521f7c7a15d77c9 data/create/loot_tables/blocks/brass_scaffolding.json
1081f76c85bdda3f68f9a190fb2a8dcd45b0e17c data/create/loot_tables/blocks/brass_tunnel.json
2e21a06c0d671e543bffecb0b67d97b51fa83ddc data/create/loot_tables/blocks/brown_nixie_tube.json
be99e48382ef8ccfb94c227c4dec7b627b4128e7 data/create/loot_tables/blocks/brown_sail.json
@ -3488,10 +3433,8 @@ c2b075008849e152f20e8da946e89c9722325df6 data/create/loot_tables/blocks/content_
28856dc862efc6bcc421d035d26386740458f868 data/create/loot_tables/blocks/controller_rail.json
2c2785e39e1891dff2c50cba93e814b56d935154 data/create/loot_tables/blocks/controls.json
3abf04f6132955275ad490668cd28f481afb4ec2 data/create/loot_tables/blocks/copper_backtank.json
6697e619d5c6dcb81aad4f5c88ba319d13665b35 data/create/loot_tables/blocks/copper_bars.json
8010db6b2427536c74312c85425b3ba83abc363c data/create/loot_tables/blocks/copper_casing.json
bb51540df81ea359cdc9d8a4d08ba6410ecd4919 data/create/loot_tables/blocks/copper_ladder.json
ac80fa6b1d968ddab6c3bf187a99a4cf24f30710 data/create/loot_tables/blocks/copper_scaffolding.json
31b3e00f6ab3e593a0d6abd42961b3e5e03fc888 data/create/loot_tables/blocks/copper_shingle_slab.json
485bc910ebaa9f509d15a0a4ddff50e5bf4d187c data/create/loot_tables/blocks/copper_shingle_stairs.json
dccfbda7fd3a7a75c323dea619d8d309ae980469 data/create/loot_tables/blocks/copper_shingles.json
@ -3499,7 +3442,6 @@ dccfbda7fd3a7a75c323dea619d8d309ae980469 data/create/loot_tables/blocks/copper_s
8abac40a29800a0ca18c50ec8ce346cad15ad47a data/create/loot_tables/blocks/copper_tile_stairs.json
3eddbc442b37ba3bb309eaf26c2f4ad06de40df7 data/create/loot_tables/blocks/copper_tiles.json
6430f776846393ab6d70d23faeccb3e353c66129 data/create/loot_tables/blocks/copper_valve_handle.json
5c1df8443043b3fe3b665dba348e2ff188bcbe31 data/create/loot_tables/blocks/copycat_bars.json
5c1df8443043b3fe3b665dba348e2ff188bcbe31 data/create/loot_tables/blocks/copycat_base.json
565441b809ded4218e69abd88bf26abee763ca08 data/create/loot_tables/blocks/copycat_panel.json
3f3df2ffc1efb1492a2a42c1eff14e5cad06b6f5 data/create/loot_tables/blocks/copycat_step.json
@ -3680,14 +3622,12 @@ f3502cb946b3997856b3a9bdb2d9f4ce01e2013a data/create/loot_tables/blocks/haunted_
c8083116de11904c1c6d53e1b869e322d18c589a data/create/loot_tables/blocks/horizontal_framed_glass.json
5f5ffb0271b312e2696493b336653b4aeeb3dca2 data/create/loot_tables/blocks/horizontal_framed_glass_pane.json
a58348cd828fb2b0f4bc116ebc14645a97ead843 data/create/loot_tables/blocks/hose_pulley.json
b9ec6580975279dcfd84a70d31e847fc0aee9d68 data/create/loot_tables/blocks/industrial_iron_block.json
feed1cd9639de957c9b34212d1c4aef2044d1e31 data/create/loot_tables/blocks/item_drain.json
af3042824de4aff38e27657ebb084077a7d4f925 data/create/loot_tables/blocks/item_vault.json
db23fee08abdb61fe2f200a5016e41523159feef data/create/loot_tables/blocks/jungle_window.json
67f7d9162d3b86e198ab7faa1ddcfdfce605d10c data/create/loot_tables/blocks/jungle_window_pane.json
7ed68e33a8c488242a2d9039797498068797c5a6 data/create/loot_tables/blocks/large_bogey.json
a70fcfe474ba023adc9c326218c5664fbd7b58f8 data/create/loot_tables/blocks/large_cogwheel.json
9edccdfed011fdbac3a8911684b73fd029df87b4 data/create/loot_tables/blocks/large_water_wheel.json
81013913c3cc88e2390608420a2911d57414bd2c data/create/loot_tables/blocks/layered_andesite.json
a89d357d3b8d7633bffe12a4197ab19cba891005 data/create/loot_tables/blocks/layered_asurine.json
93950e03d141e59948c4aadca09ecd8b898a5276 data/create/loot_tables/blocks/layered_calcite.json
@ -3738,6 +3678,7 @@ a21c4e4eebeff2daf1f081cd6226f29adfeade7c data/create/loot_tables/blocks/mechanic
b8f5a9201775b711195a01882888307dd273aeab data/create/loot_tables/blocks/mechanical_plough.json
ff55d31ae8f7a8943f1e9fcc330d18e246566997 data/create/loot_tables/blocks/mechanical_press.json
8f885b8cec8f1ef9e35bd9b93a64a0f6e14c31b0 data/create/loot_tables/blocks/mechanical_pump.json
fda8ee4cd0f5a29267b10e53b013dc75cee253e9 data/create/loot_tables/blocks/mechanical_roller.json
6c88dd3f096f2a7572573158f8e6d9f4b3dedae0 data/create/loot_tables/blocks/mechanical_saw.json
fcd800d7abf5dc5ce50b6fff6f2fc934b3d47b4b data/create/loot_tables/blocks/metal_bracket.json
afdff197c9d1a6940e988c00435135f9705fd0e5 data/create/loot_tables/blocks/metal_girder.json
@ -3957,7 +3898,6 @@ f74bc454bda585bc5ab0b5b3e0b4d345a6ff039b data/create/loot_tables/blocks/train_tr
183444f27542a3a7ab933243b61c2714357f7361 data/create/loot_tables/blocks/warped_window.json
2fa711af9d00bd47f256fe6b0cc83a303644b1c0 data/create/loot_tables/blocks/warped_window_pane.json
e6c1f19127a3fcf010ed6fb004a40a69458c54e3 data/create/loot_tables/blocks/water_wheel.json
5c1df8443043b3fe3b665dba348e2ff188bcbe31 data/create/loot_tables/blocks/water_wheel_structure.json
815cddd9fb217a69b3a0ac4554d830c04d0ef173 data/create/loot_tables/blocks/waxed_copper_shingle_slab.json
b28ea9be9de982b6561839c61f4a7264c8ba4171 data/create/loot_tables/blocks/waxed_copper_shingle_stairs.json
b26f12b81e4f801cc107b5c6316ad9006c5ea391 data/create/loot_tables/blocks/waxed_copper_shingles.json
@ -4005,11 +3945,8 @@ efb30e3d24a700cf35b29406ee0b5d5021545d51 data/create/loot_tables/blocks/zinc_blo
d54859b2eb9c8c06aca8a8484bc65c8e4e0bb80a data/create/loot_tables/blocks/zinc_ore.json
b65bac8bc2fbfd476040c1aab1c0588b8bd59ebe data/create/recipes/acacia_window.json
35b4da9c14da60584c32e959efc2223f64bb3ec2 data/create/recipes/acacia_window_pane.json
0616eda1784861b126017ff4617ede287ffe7c7c data/create/recipes/andesite_bars_from_andesite_alloy_stonecutting.json
388a7df4c6562e35ac0280bff786226e37f0ae45 data/create/recipes/andesite_ladder_from_andesite_alloy_stonecutting.json
dcdad7a04838ef202b42f84a15243e3d2472b14e data/create/recipes/andesite_pillar_from_andesite_stonecutting.json
b1f2f8a0f78bcd856e0352d88b6392ca6d5ed74f data/create/recipes/andesite_pillar_from_stone_types_andesite_stonecutting.json
70880972e63cf9953d2c9de0492f2f2c288c5a90 data/create/recipes/andesite_scaffolding_from_andesite_alloy_stonecutting.json
a30aa616e2b62c848dd194e319a90bf7ba3db81b data/create/recipes/asurine_pillar_from_asurine_stonecutting.json
a133d4d2542c0b9309873d06a72e7efff4cee219 data/create/recipes/asurine_pillar_from_stone_types_asurine_stonecutting.json
2b291b77860254b7ba8500cf2199a04ca1fca7b5 data/create/recipes/birch_window.json
@ -4033,9 +3970,7 @@ c49e88f38ad624a56865bb293e2b81da09ebdf37 data/create/recipes/blasting/silver_ing
70b58fa5ee4ca088f5cd9d4bce2853b1bbf98780 data/create/recipes/blasting/zinc_ingot_from_crushed.json
3b1f91669d1133bb41f2d8e129d885465cb5b30e data/create/recipes/blasting/zinc_ingot_from_ore.json
2dff1a64b2c9974b768f4861ad90a9a110bdd021 data/create/recipes/blasting/zinc_ingot_from_raw_ore.json
b8364d0d29da881dce531f053b386f2a2dd63f01 data/create/recipes/brass_bars_from_plates_brass_stonecutting.json
25af3c80132496b17d71800a43538bc34812efa3 data/create/recipes/brass_ladder_from_plates_brass_stonecutting.json
50481685e206e4cbe20e3eb7d5a9819fcaa6da0f data/create/recipes/brass_scaffolding_from_plates_brass_stonecutting.json
89cc3710a1925239030329b151f9764901a647e5 data/create/recipes/calcite_pillar_from_calcite_stonecutting.json
2cf7208bfe82b26443d41c05edd321f76a3a3df0 data/create/recipes/calcite_pillar_from_stone_types_calcite_stonecutting.json
339bcf4a9c4e7b36c15970aa671af8620703b23e data/create/recipes/campfire_cooking/bread.json
@ -4045,9 +3980,7 @@ f7879d404d7a848d818278b4e788f285a9087e63 data/create/recipes/compacting/blaze_ca
ac91109efa5a253f54257904190b80a400ec6d0c data/create/recipes/compacting/diorite_from_flint.json
7657603e95ccf83dd0d4b104635db66e531d092a data/create/recipes/compacting/granite_from_flint.json
739a1d004c4be50cda2d706a64b797f66c3ca9c8 data/create/recipes/compacting/honey.json
a079cf471ed223bdec738b4c1c7d5bedbaf6db1e data/create/recipes/copper_bars_from_plates_copper_stonecutting.json
72ae29ce953c855eb52fa48e8dbde566574a45f6 data/create/recipes/copper_ladder_from_plates_copper_stonecutting.json
1be9a5dc5c6b039da6500719e9327f8528baed88 data/create/recipes/copper_scaffolding_from_plates_copper_stonecutting.json
1a03af7f858946c395cc05714dd4d0a02206d2d4 data/create/recipes/copper_shingle_slab.json
059abbf567f7b5cf376447bdbee27285b29b7f0f data/create/recipes/copper_shingle_slab_from_copper_shingles_stonecutting.json
0d7569afe35b4bf7da05cd500d1b8d9bd78f9842 data/create/recipes/copper_shingle_stairs.json
@ -4097,6 +4030,7 @@ ab875f89a22504f3d3fd6ee2aa004d5f0082f169 data/create/recipes/crafting/curiositie
07b3ca3a3e44ee1f76c69132ffa6556e027e5b0e data/create/recipes/crafting/curiosities/toolbox_dyeing.json
4e9630bad12e6879ae7357ce7c8d455dddded9a4 data/create/recipes/crafting/kinetics/adjustable_chain_gearshift.json
88de51b451469698665b7319e5b9cfb9a87ae3e0 data/create/recipes/crafting/kinetics/analog_lever.json
8dc42e21f4d45dee83645b0cc96543bbe0ea4472 data/create/recipes/crafting/kinetics/andesite_ladder.json
cf1f3a6306d47025cebe153cf05949ef69ccbe5a data/create/recipes/crafting/kinetics/attribute_filter.json
059d12526529b2896ed583555373afa31839a0de data/create/recipes/crafting/kinetics/basin.json
dcf98e667d321fb4bd9fa6dfec7927a84cdbd5d6 data/create/recipes/crafting/kinetics/belt_connector.json
@ -4157,7 +4091,6 @@ f4fbb11ef55f3431bd387f3f6f258513bfbc8011 data/create/recipes/crafting/kinetics/i
8f7110447f039f80a6f5b1d854bc760c3d77da82 data/create/recipes/crafting/kinetics/item_vault.json
7f105694e02d4ce69a02740edfa4a0d0bc4f4eac data/create/recipes/crafting/kinetics/large_cogwheel.json
197c174c28f294b23ae6496b7a31c35e7e8b4771 data/create/recipes/crafting/kinetics/large_cogwheelfrom_little.json
5609b12dde7127965c70da2760038c456ba3cfd6 data/create/recipes/crafting/kinetics/large_water_wheel.json
0397b107ab380cd23390c96f298971a70e9bceef data/create/recipes/crafting/kinetics/light_blue_seat.json
aa06f0594e1b2d31aa41bace309ed95a16529498 data/create/recipes/crafting/kinetics/light_blue_seat_from_other_seat.json
bb8759b51aef768fa841962b9ad49676a6096a1c data/create/recipes/crafting/kinetics/light_blue_valve_handle_from_other_valve_handle.json
@ -4182,6 +4115,7 @@ e8d842e3bd9949ea12682d9cddf29e7d54f926ec data/create/recipes/crafting/kinetics/m
8a2f9068d6fab81f46699f897e619461ca89e38f data/create/recipes/crafting/kinetics/mechanical_plough.json
be0b5c980c310807253d54006a714534a4b27065 data/create/recipes/crafting/kinetics/mechanical_press.json
4307cc2c988ac19602f2f86afa2146c7e7fef026 data/create/recipes/crafting/kinetics/mechanical_pump.json
316c72e1a2ec264b33f98a51125a6de20e679c38 data/create/recipes/crafting/kinetics/mechanical_roller.json
ce28bcb47a379976d4a1bdfcfd1cdd0bae0bcdae data/create/recipes/crafting/kinetics/mechanical_saw.json
353146e9501096b4cd9632ad5500b0a2406c6f5d data/create/recipes/crafting/kinetics/metal_bracket.json
0ef8088b775f551c6f5b44f21f419fba366a971e data/create/recipes/crafting/kinetics/metal_girder.json
@ -4235,7 +4169,7 @@ c38984c432bd410261aaf6a6f30744c58481b325 data/create/recipes/crafting/kinetics/t
5e2af5ce3957d5ce4f54ceb667dcfed5cffafb32 data/create/recipes/crafting/kinetics/train_trapdoor.json
8494f5fcd85a740fa0f0384e3522d8cdd905ce49 data/create/recipes/crafting/kinetics/turntable.json
057c889b0a306f44b8835c896663154ccd9ff12f data/create/recipes/crafting/kinetics/vertical_gearboxfrom_conversion.json
152e63ade2759d01a07b9e71a3c60dfe5ea15ba8 data/create/recipes/crafting/kinetics/water_wheel.json
4fb009b86a51b2e259bd1f73848803f6276dd820 data/create/recipes/crafting/kinetics/water_wheel.json
06b5b371ae9dd81df8fd3dee6d3559b1ed0db35c data/create/recipes/crafting/kinetics/weighted_ejector.json
f508d510576c93712e7f5265345a32e8818bbf0d data/create/recipes/crafting/kinetics/whisk.json
98546e5e5f1fe111e84c4a17569c8e7b57f8cc8d data/create/recipes/crafting/kinetics/white_sail.json
@ -5717,7 +5651,7 @@ d063e12c9ef75f39518c6d129ea35d833464d547 data/create/tags/blocks/toolboxes.json
9460e92c8e483446318b849abe7e6f52dcd4a269 data/create/tags/blocks/tree_attachments.json
50936b211d94167a35ec78c89954082a336b6269 data/create/tags/blocks/valve_handles.json
eac71740fb12bdb38b5dfaa2268613d7ba82b809 data/create/tags/blocks/windmill_sails.json
84b63dd3da12f34248474941d961b1e71837917e data/create/tags/blocks/wrench_pickup.json
96671fd75d4209280940ef774c4185f33610a64d data/create/tags/blocks/wrench_pickup.json
a8bdc387cfa6296ebcc4af14323e2ddb632234dc data/create/tags/fluids/bottomless/allow.json
74700d556ca80c7a1db5fd4efb09c3ddb26cad66 data/create/tags/fluids/bottomless/deny.json
74700d556ca80c7a1db5fd4efb09c3ddb26cad66 data/create/tags/items/blaze_burner_fuel/regular.json
@ -5758,8 +5692,7 @@ f3e20d8b3ca5652d3975da680740cc36326fdfc9 data/create/tags/items/vanilla_stripped
9fc688d8fac1033c7b8f4b8de1138e56d2faf527 data/forge/tags/blocks/ores_in_ground/deepslate.json
d5ea262a0f5fb210612d22521818e26cf08e591a data/forge/tags/blocks/ores_in_ground/stone.json
ad8fa04f7bbbafd70d0ce158af78a35e899301e2 data/forge/tags/blocks/relocation_not_supported.json
cffe82d6f1d2eefdaf200eedfe50b590aa5ffbbb data/forge/tags/blocks/storage_blocks.json
ecd6eda3669e4d4df367df99a7692cc0dd04e7ee data/forge/tags/blocks/storage_blocks/andesite_alloy.json
66065a698fca917446a0fb766593dbcc77fabeac data/forge/tags/blocks/storage_blocks.json
ff1900963bc4cd8ceffa78d58ef1952ceacb2fb7 data/forge/tags/blocks/storage_blocks/brass.json
823d05187626797205381d4620a84abda3bc8f89 data/forge/tags/blocks/storage_blocks/raw_zinc.json
7f71a774800111e50b42de0e6159ed2d2a807d32 data/forge/tags/blocks/storage_blocks/zinc.json
@ -5792,8 +5725,7 @@ fb9bfb4c84ed9cf2da8c4b2fbc4cd4d9f37d3016 data/forge/tags/items/plates/gold.json
d82758dd3c2972fa94736733dc6b3944129f5a11 data/forge/tags/items/plates/obsidian.json
dc96331cded39b2d2f24853f4dd6c1f6f3863115 data/forge/tags/items/raw_materials.json
dc96331cded39b2d2f24853f4dd6c1f6f3863115 data/forge/tags/items/raw_materials/zinc.json
cffe82d6f1d2eefdaf200eedfe50b590aa5ffbbb data/forge/tags/items/storage_blocks.json
ecd6eda3669e4d4df367df99a7692cc0dd04e7ee data/forge/tags/items/storage_blocks/andesite_alloy.json
66065a698fca917446a0fb766593dbcc77fabeac data/forge/tags/items/storage_blocks.json
ff1900963bc4cd8ceffa78d58ef1952ceacb2fb7 data/forge/tags/items/storage_blocks/brass.json
823d05187626797205381d4620a84abda3bc8f89 data/forge/tags/items/storage_blocks/raw_zinc.json
7f71a774800111e50b42de0e6159ed2d2a807d32 data/forge/tags/items/storage_blocks/zinc.json
@ -5802,13 +5734,13 @@ cfa16b75227c9bf4f245c97ac55999b3903e5471 data/forge/tags/items/stripped_logs.jso
e002dfedc5e8762de0f97ea1f3fa546e92e748ae data/forge/tags/items/tools/wrench.json
2db7759fe036160c14c6ed19a68604ca16f4de60 data/minecraft/tags/blocks/azalea_root_replaceable.json
9f7a428085b1aac66da32a43e9d51c7efc1f0d81 data/minecraft/tags/blocks/beacon_base_blocks.json
ec81fd87e63a7e736440d8826c7c5e1b16b4cc67 data/minecraft/tags/blocks/climbable.json
f5cc2ea490ede338c9ea94a5775ad626b0ebc83b data/minecraft/tags/blocks/climbable.json
e16d74571ae10007f06f3b86ddf05d3ca9b73559 data/minecraft/tags/blocks/doors.json
2db7759fe036160c14c6ed19a68604ca16f4de60 data/minecraft/tags/blocks/dripstone_replaceable_blocks.json
69f596fcb065e26b02ce246760432b5174191b76 data/minecraft/tags/blocks/impermeable.json
2db7759fe036160c14c6ed19a68604ca16f4de60 data/minecraft/tags/blocks/lush_ground_replaceable.json
f4a1cdc4ffe7dd8412e8be369a48d19cf31a7f77 data/minecraft/tags/blocks/mineable/axe.json
a7eb0e379696c39c6f5a4603e29d3d8cc4fbf50c data/minecraft/tags/blocks/mineable/pickaxe.json
e2ba2b22fbda681faa4db4a32f6e15d2c7946fec data/minecraft/tags/blocks/mineable/axe.json
1c1c974423a0d5668d20ebabfe4444e7fb1fe372 data/minecraft/tags/blocks/mineable/pickaxe.json
2db7759fe036160c14c6ed19a68604ca16f4de60 data/minecraft/tags/blocks/moss_replaceable.json
e157c1d3af30e409e34bbefbe15a037e6e1c8daa data/minecraft/tags/blocks/needs_iron_tool.json
a08f67865337f62601c5e333b4011382d10020e4 data/minecraft/tags/blocks/needs_stone_tool.json

View file

@ -1,17 +1,32 @@
{
"variants": {
"facing=north": {
"facing=north,waterlogged=false": {
"model": "create:block/mechanical_harvester/block"
},
"facing=south": {
"facing=south,waterlogged=false": {
"model": "create:block/mechanical_harvester/block",
"y": 180
},
"facing=west": {
"facing=west,waterlogged=false": {
"model": "create:block/mechanical_harvester/block",
"y": 270
},
"facing=east": {
"facing=east,waterlogged=false": {
"model": "create:block/mechanical_harvester/block",
"y": 90
},
"facing=north,waterlogged=true": {
"model": "create:block/mechanical_harvester/block"
},
"facing=south,waterlogged=true": {
"model": "create:block/mechanical_harvester/block",
"y": 180
},
"facing=west,waterlogged=true": {
"model": "create:block/mechanical_harvester/block",
"y": 270
},
"facing=east,waterlogged=true": {
"model": "create:block/mechanical_harvester/block",
"y": 90
}

View file

@ -1,17 +1,32 @@
{
"variants": {
"facing=north": {
"facing=north,waterlogged=false": {
"model": "create:block/mechanical_plough"
},
"facing=south": {
"facing=south,waterlogged=false": {
"model": "create:block/mechanical_plough",
"y": 180
},
"facing=west": {
"facing=west,waterlogged=false": {
"model": "create:block/mechanical_plough",
"y": 270
},
"facing=east": {
"facing=east,waterlogged=false": {
"model": "create:block/mechanical_plough",
"y": 90
},
"facing=north,waterlogged=true": {
"model": "create:block/mechanical_plough"
},
"facing=south,waterlogged=true": {
"model": "create:block/mechanical_plough",
"y": 180
},
"facing=west,waterlogged=true": {
"model": "create:block/mechanical_plough",
"y": 270
},
"facing=east,waterlogged=true": {
"model": "create:block/mechanical_plough",
"y": 90
}

View file

@ -0,0 +1,34 @@
{
"variants": {
"facing=north,waterlogged=false": {
"model": "create:block/mechanical_roller/block"
},
"facing=south,waterlogged=false": {
"model": "create:block/mechanical_roller/block",
"y": 180
},
"facing=west,waterlogged=false": {
"model": "create:block/mechanical_roller/block",
"y": 270
},
"facing=east,waterlogged=false": {
"model": "create:block/mechanical_roller/block",
"y": 90
},
"facing=north,waterlogged=true": {
"model": "create:block/mechanical_roller/block"
},
"facing=south,waterlogged=true": {
"model": "create:block/mechanical_roller/block",
"y": 180
},
"facing=west,waterlogged=true": {
"model": "create:block/mechanical_roller/block",
"y": 270
},
"facing=east,waterlogged=true": {
"model": "create:block/mechanical_roller/block",
"y": 90
}
}
}

View file

@ -312,6 +312,7 @@
"block.create.mechanical_plough": "\u0265bno\u05DF\u0500 \u05DF\u0250\u0254\u0131u\u0250\u0265\u0254\u01DDW",
"block.create.mechanical_press": "ss\u01DD\u0279\u0500 \u05DF\u0250\u0254\u0131u\u0250\u0265\u0254\u01DDW",
"block.create.mechanical_pump": "d\u026Fn\u0500 \u05DF\u0250\u0254\u0131u\u0250\u0265\u0254\u01DDW",
"block.create.mechanical_roller": "\u0279\u01DD\u05DF\u05DFo\u1D1A \u05DF\u0250\u0254\u0131u\u0250\u0265\u0254\u01DDW",
"block.create.mechanical_saw": "\u028D\u0250S \u05DF\u0250\u0254\u0131u\u0250\u0265\u0254\u01DDW",
"block.create.metal_bracket": "\u0287\u01DD\u029E\u0254\u0250\u0279\u15FA \u05DF\u0250\u0287\u01DDW",
"block.create.metal_girder": "\u0279\u01DDp\u0279\u0131\u2141 \u05DF\u0250\u0287\u01DDW",

View file

@ -6,8 +6,6 @@
"block.create.acacia_window_pane": "Acacia Window Pane",
"block.create.adjustable_chain_gearshift": "Adjustable Chain Gearshift",
"block.create.analog_lever": "Analog Lever",
"block.create.andesite_alloy_block": "Block of Andesite Alloy",
"block.create.andesite_bars": "Andesite Bars",
"block.create.andesite_belt_funnel": "Andesite Belt Funnel",
"block.create.andesite_casing": "Andesite Casing",
"block.create.andesite_encased_cogwheel": "Andesite Encased Cogwheel",
@ -16,7 +14,6 @@
"block.create.andesite_funnel": "Andesite Funnel",
"block.create.andesite_ladder": "Andesite Ladder",
"block.create.andesite_pillar": "Andesite Pillar",
"block.create.andesite_scaffolding": "Andesite Scaffolding",
"block.create.andesite_tunnel": "Andesite Tunnel",
"block.create.asurine": "Asurine",
"block.create.asurine_pillar": "Asurine Pillar",
@ -35,7 +32,6 @@
"block.create.blue_seat": "Blue Seat",
"block.create.blue_toolbox": "Blue Toolbox",
"block.create.blue_valve_handle": "Blue Valve Handle",
"block.create.brass_bars": "Brass Bars",
"block.create.brass_belt_funnel": "Brass Belt Funnel",
"block.create.brass_block": "Block of Brass",
"block.create.brass_casing": "Brass Casing",
@ -44,7 +40,6 @@
"block.create.brass_encased_shaft": "Brass Encased Shaft",
"block.create.brass_funnel": "Brass Funnel",
"block.create.brass_ladder": "Brass Ladder",
"block.create.brass_scaffolding": "Brass Scaffolding",
"block.create.brass_tunnel": "Brass Tunnel",
"block.create.brown_nixie_tube": "Brown Nixie Tube",
"block.create.brown_sail": "Brown Sail",
@ -63,10 +58,8 @@
"block.create.controller_rail": "Controller Rail",
"block.create.controls": "Train Controls",
"block.create.copper_backtank": "Copper Backtank",
"block.create.copper_bars": "Copper Bars",
"block.create.copper_casing": "Copper Casing",
"block.create.copper_ladder": "Copper Ladder",
"block.create.copper_scaffolding": "Copper Scaffolding",
"block.create.copper_shingle_slab": "Copper Shingle Slab",
"block.create.copper_shingle_stairs": "Copper Shingle Stairs",
"block.create.copper_shingles": "Copper Shingles",
@ -74,7 +67,6 @@
"block.create.copper_tile_stairs": "Copper Tile Stairs",
"block.create.copper_tiles": "Copper Tiles",
"block.create.copper_valve_handle": "Copper Valve Handle",
"block.create.copycat_bars": "Copycat Bars",
"block.create.copycat_base": "Copycat Base",
"block.create.copycat_panel": "Copycat Panel",
"block.create.copycat_step": "Copycat Step",
@ -257,14 +249,12 @@
"block.create.horizontal_framed_glass": "Horizontal Framed Glass",
"block.create.horizontal_framed_glass_pane": "Horizontal Framed Glass Pane",
"block.create.hose_pulley": "Hose Pulley",
"block.create.industrial_iron_block": "Block of Industrial Iron",
"block.create.item_drain": "Item Drain",
"block.create.item_vault": "Item Vault",
"block.create.jungle_window": "Jungle Window",
"block.create.jungle_window_pane": "Jungle Window Pane",
"block.create.large_bogey": "Large Bogey",
"block.create.large_cogwheel": "Large Cogwheel",
"block.create.large_water_wheel": "Large Water Wheel",
"block.create.layered_andesite": "Layered Andesite",
"block.create.layered_asurine": "Layered Asurine",
"block.create.layered_calcite": "Layered Calcite",
@ -315,6 +305,7 @@
"block.create.mechanical_plough": "Mechanical Plough",
"block.create.mechanical_press": "Mechanical Press",
"block.create.mechanical_pump": "Mechanical Pump",
"block.create.mechanical_roller": "Mechanical Roller",
"block.create.mechanical_saw": "Mechanical Saw",
"block.create.metal_bracket": "Metal Bracket",
"block.create.metal_girder": "Metal Girder",
@ -534,7 +525,6 @@
"block.create.warped_window": "Warped Window",
"block.create.warped_window_pane": "Warped Window Pane",
"block.create.water_wheel": "Water Wheel",
"block.create.water_wheel_structure": "Large Water Wheel",
"block.create.waxed_copper_shingle_slab": "Waxed Copper Shingle Slab",
"block.create.waxed_copper_shingle_stairs": "Waxed Copper Shingle Stairs",
"block.create.waxed_copper_shingles": "Waxed Copper Shingles",
@ -890,6 +880,8 @@
"death.attack.create.fan_lava.player": "%1$s was thrown into a smelter by %2$s",
"death.attack.create.mechanical_drill": "%1$s was impaled by a Mechanical Drill",
"death.attack.create.mechanical_drill.player": "%1$s was thrown in front of a Drill by %2$s",
"death.attack.create.mechanical_roller": "%1$s was flattened by a Mechanical Roller",
"death.attack.create.mechanical_roller.player": "%1$s was thrown in front of a Mechanical Roller by %2$s",
"death.attack.create.mechanical_saw": "%1$s got cut in half by a Mechanical Saw",
"death.attack.create.mechanical_saw.player": "%1$s was thrown into a Saw by %2$s",
"death.attack.create.potato_cannon": "%1$s was shot by %2$s's Potato Cannon",
@ -1050,8 +1042,6 @@
"create.terrainzapper.usingBlock": "Using: %1$s",
"create.terrainzapper.leftClickToSet": "Left-Click a Block to set Material",
"create.large_water_wheel.not_enough_space": "Clear Blocks for Placement",
"create.minecart_coupling.two_couplings_max": "Minecarts cannot have more than two couplings each",
"create.minecart_coupling.unloaded": "Parts of your train seem to be in unloaded chunks",
"create.minecart_coupling.no_loops": "Couplings cannot form a loop",
@ -1069,42 +1059,26 @@
"create.contraptions.cart_movement_mode.rotate": "Always face toward motion",
"create.contraptions.cart_movement_mode.rotate_paused": "Pause actors while rotating",
"create.contraptions.cart_movement_mode.rotation_locked": "Lock rotation",
"create.contraptions.roller_mode": "Roller Mode",
"create.contraptions.roller_mode.tunnel_pave": "Clear Blocks and Pave",
"create.contraptions.roller_mode.straight_fill": "Straight Fill Below",
"create.contraptions.roller_mode.wide_fill": "Sloped Fill Below",
"create.contraptions.windmill.rotation_direction": "Rotation Direction",
"create.contraptions.clockwork.clock_hands": "Clock Hand Arrangement",
"create.contraptions.clockwork.clock_hands": "Clock Hands",
"create.contraptions.clockwork.hour_first": "Hour hand first",
"create.contraptions.clockwork.minute_first": "Minute hand first",
"create.contraptions.clockwork.hour_first_24": "24-Hour hand first",
"create.logistics.crafter.connected": "Connected Crafters",
"create.logistics.crafter.click_to_merge": "Click to merge Inventories",
"create.logistics.crafter.click_to_separate": "Click to separate Inventories",
"create.logistics.filter": "Filter",
"create.logistics.recipe_filter": "Recipe Filter",
"create.logistics.fluid_filter": "Fluid Filter",
"create.logistics.firstFrequency": "Frequency #1",
"create.logistics.secondFrequency": "Frequency #2",
"create.logistics.filter.click_to_set": "Click with item to set",
"create.logistics.filter.click_to_replace": "Click with item to replace",
"create.logistics.filter.hold_to_set_amount": "Click and hold for amount",
"create.logistics.filter.extracted_amount": "Extracted Amount",
"create.logistics.filter.any_amount_short": "Any",
"create.logistics.filter.up_to": "Up to",
"create.logistics.filter.exactly": "Exactly",
"create.logistics.creative_crate.supply": "Infinite Supply",
"create.logistics.train_observer.cargo_filter": "Cargo Filter",
"create.logistics.firstFrequency": "Freq. #1",
"create.logistics.secondFrequency": "Freq. #2",
"create.logistics.filter.apply": "Applied filter to %1$s.",
"create.logistics.filter.apply_click_again": "Applied filter to %1$s, click again to copy the amount.",
"create.logistics.filter.apply_count": "Applied extraction count to filter.",
"create.logistics.filter.invalid_item": "Cannot use this item here.",
"create.kinetics.creative_motor.rotation_speed": "Generated Speed in RPM",
"create.kinetics.speed_controller.rotation_speed": "Targeted Speed in RPM",
"create.logistics.redstone_interval": "Redstone Interval",
"create.contraptions.contoller.target": "Targeted Component",
"create.contraptions.chassis.radius": "Radius when Sticky",
"create.contraptions.chassis.range": "Range of Sticky Sides",
"create.contraptions.chassis.distance": "Distance",
"create.gui.value_settings.hold_to_edit": "Click and hold to edit",
"create.gui.value_settings.release_to_confirm": "Release %1$s to Confirm",
"create.gui.goggles.generator_stats": "Generator Stats:",
"create.gui.goggles.kinetic_stats": "Kinetic Stats:",
"create.gui.goggles.at_current_speed": "at current speed",
@ -1395,7 +1369,7 @@
"create.weighted_ejector.targeting": "Ejecting to [%1$s,%2$s,%3$s]",
"create.weighted_ejector.stack_size": "Ejected Stack Size",
"create.logistics.when_multiple_outputs_available": "Distribution Method",
"create.logistics.when_multiple_outputs_available": "When Multiple Outputs Available",
"create.mechanical_arm.selection_mode.round_robin": "Round Robin",
"create.mechanical_arm.selection_mode.forced_round_robin": "Forced Round Robin",
@ -1688,6 +1662,20 @@
"create.contraption.controls.actor_toggle.on": "On",
"create.contraption.controls.actor_toggle.off": "Off",
"create.contraption.controls.floor_unreachable": "Unreachable",
"create.contraption.door_control": "Onboard Door Control",
"create.contraption.door_control.all": "Open All Doors",
"create.contraption.door_control.all.short": "Open All",
"create.contraption.door_control.north": "North Side Only",
"create.contraption.door_control.north.short": "North",
"create.contraption.door_control.east": "East Side Only",
"create.contraption.door_control.east.short": "East",
"create.contraption.door_control.south": "South Side Only",
"create.contraption.door_control.south.short": "South",
"create.contraption.door_control.west": "West Side Only",
"create.contraption.door_control.west.short": "West",
"create.contraption.door_control.none": "Keep Doors Closed",
"create.contraption.door_control.none.short": "None",
"create.contraption.door_control.player_facing": "You are facing: %1$s",
"create.display_link.set": "Targeted position selected",
"create.display_link.success": "Successfully bound to targeted position",

View file

@ -0,0 +1,3 @@
{
"parent": "create:block/mechanical_roller/item"
}

View file

@ -0,0 +1,34 @@
{
"parent": "minecraft:recipes/root",
"rewards": {
"recipes": [
"create:crafting/kinetics/mechanical_roller"
]
},
"criteria": {
"has_item": {
"trigger": "minecraft:inventory_changed",
"conditions": {
"items": [
{
"items": [
"create:andesite_casing"
]
}
]
}
},
"has_the_recipe": {
"trigger": "minecraft:recipe_unlocked",
"conditions": {
"recipe": "create:crafting/kinetics/mechanical_roller"
}
}
},
"requirements": [
[
"has_item",
"has_the_recipe"
]
]
}

View file

@ -0,0 +1,20 @@
{
"type": "minecraft:block",
"pools": [
{
"rolls": 1.0,
"bonus_rolls": 0.0,
"entries": [
{
"type": "minecraft:item",
"name": "create:mechanical_roller"
}
],
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
]
}
]
}

View file

@ -0,0 +1,22 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"A",
"C",
"I"
],
"key": {
"C": {
"item": "create:andesite_casing"
},
"A": {
"item": "create:electron_tube"
},
"I": {
"item": "create:crushing_wheel"
}
},
"result": {
"item": "create:mechanical_roller"
}
}

View file

@ -58,6 +58,7 @@
"create:elevator_contact",
"create:mechanical_harvester",
"create:mechanical_plough",
"create:mechanical_roller",
"create:white_seat",
"create:orange_seat",
"create:magenta_seat",

View file

@ -110,6 +110,7 @@
"create:elevator_contact",
"create:mechanical_harvester",
"create:mechanical_plough",
"create:mechanical_roller",
"create:andesite_casing",
"create:brass_casing",
"create:copper_casing",

View file

@ -18,6 +18,8 @@ import com.simibubi.create.content.contraptions.components.actors.PSIInstance;
import com.simibubi.create.content.contraptions.components.actors.PortableFluidInterfaceBlockEntity;
import com.simibubi.create.content.contraptions.components.actors.PortableItemInterfaceBlockEntity;
import com.simibubi.create.content.contraptions.components.actors.PortableStorageInterfaceRenderer;
import com.simibubi.create.content.contraptions.components.actors.RollerBlockEntity;
import com.simibubi.create.content.contraptions.components.actors.RollerRenderer;
import com.simibubi.create.content.contraptions.components.actors.controls.ContraptionControlsBlockEntity;
import com.simibubi.create.content.contraptions.components.actors.controls.ContraptionControlsRenderer;
import com.simibubi.create.content.contraptions.components.clock.CuckooClockBlockEntity;
@ -538,6 +540,12 @@ public class AllBlockEntityTypes {
.renderer(() -> HarvesterRenderer::new)
.register();
public static final BlockEntityEntry<RollerBlockEntity> MECHANICAL_ROLLER =
REGISTRATE.blockEntity("mechanical_roller", RollerBlockEntity::new)
.validBlocks(AllBlocks.MECHANICAL_ROLLER)
.renderer(() -> RollerRenderer::new)
.register();
public static final BlockEntityEntry<PortableItemInterfaceBlockEntity> PORTABLE_STORAGE_INTERFACE =
REGISTRATE
.blockEntity("portable_storage_interface", PortableItemInterfaceBlockEntity::new)

View file

@ -26,6 +26,8 @@ import com.simibubi.create.content.contraptions.components.actors.PloughBlock;
import com.simibubi.create.content.contraptions.components.actors.PloughMovementBehaviour;
import com.simibubi.create.content.contraptions.components.actors.PortableStorageInterfaceBlock;
import com.simibubi.create.content.contraptions.components.actors.PortableStorageInterfaceMovement;
import com.simibubi.create.content.contraptions.components.actors.RollerBlock;
import com.simibubi.create.content.contraptions.components.actors.RollerMovementBehaviour;
import com.simibubi.create.content.contraptions.components.actors.SawMovementBehaviour;
import com.simibubi.create.content.contraptions.components.actors.SeatBlock;
import com.simibubi.create.content.contraptions.components.actors.SeatInteractionBehaviour;
@ -233,6 +235,7 @@ import com.simibubi.create.content.logistics.trains.track.StandardBogeyBlock;
import com.simibubi.create.content.logistics.trains.track.TrackBlock;
import com.simibubi.create.content.logistics.trains.track.TrackBlockItem;
import com.simibubi.create.content.logistics.trains.track.TrackBlockStateGenerator;
import com.simibubi.create.content.logistics.trains.track.TrackModel;
import com.simibubi.create.content.schematics.block.SchematicTableBlock;
import com.simibubi.create.content.schematics.block.SchematicannonBlock;
import com.simibubi.create.foundation.block.BlockStressDefaults;
@ -1239,7 +1242,7 @@ public class AllBlocks {
.item()
.transform(customItemModel())
.register();
public static final BlockEntry<CartAssemblerBlock> CART_ASSEMBLER =
REGISTRATE.block("cart_assembler", CartAssemblerBlock::new)
.initialProperties(SharedProperties::stone)
@ -1390,7 +1393,7 @@ public class AllBlocks {
.item(RedstoneContactItem::new)
.transform(customItemModel("_", "block"))
.register();
public static final BlockEntry<ElevatorContactBlock> ELEVATOR_CONTACT =
REGISTRATE.block("elevator_contact", ElevatorContactBlock::new)
.initialProperties(SharedProperties::softMetal)
@ -1431,6 +1434,19 @@ public class AllBlocks {
.simpleItem()
.register();
public static final BlockEntry<RollerBlock> MECHANICAL_ROLLER =
REGISTRATE.block("mechanical_roller", RollerBlock::new)
.initialProperties(SharedProperties::stone)
.properties(p -> p.color(MaterialColor.COLOR_GRAY)
.noOcclusion())
.transform(axeOrPickaxe())
.onRegister(movementBehaviour(new RollerMovementBehaviour()))
.blockstate(BlockStateGen.horizontalBlockProvider(true))
.addLayer(() -> RenderType::cutoutMipped)
.item()
.transform(customItemModel())
.register();
public static final DyedBlockList<SeatBlock> SEATS = new DyedBlockList<>(colour -> {
String colourName = colour.getSerializedName();
SeatMovementBehaviour movementBehaviour = new SeatMovementBehaviour();
@ -1617,6 +1633,7 @@ public class AllBlocks {
.noOcclusion())
.addLayer(() -> RenderType::cutoutMipped)
.transform(pickaxeOnly())
.onRegister(CreateRegistrate.blockModel(() -> TrackModel::new))
.blockstate(new TrackBlockStateGenerator()::generate)
.tag(AllBlockTags.RELOCATION_NOT_SUPPORTED.tag)
.lang("Train Track")
@ -1780,8 +1797,7 @@ public class AllBlocks {
public static final BlockEntry<ItemVaultBlock> ITEM_VAULT = REGISTRATE.block("item_vault", ItemVaultBlock::new)
.initialProperties(SharedProperties::softMetal)
.properties(p -> p.color(
MaterialColor.TERRACOTTA_BLUE))
.properties(p -> p.color(MaterialColor.TERRACOTTA_BLUE))
.properties(p -> p.sound(SoundType.NETHERITE_BLOCK)
.explosionResistance(1200))
.transform(pickaxeOnly())

View file

@ -52,6 +52,9 @@ public class AllPartialModels {
ANALOG_LEVER_INDICATOR = block("analog_lever/indicator"), FUNNEL_FLAP = block("funnel/flap"),
BELT_FUNNEL_FLAP = block("belt_funnel/flap"), BELT_TUNNEL_FLAP = block("belt_tunnel/flap"),
FLEXPEATER_INDICATOR = block("diodes/indicator"),
ROLLER_WHEEL = block("mechanical_roller/wheel"),
ROLLER_FRAME = block("mechanical_roller/frame"),
CUCKOO_MINUTE_HAND = block("cuckoo_clock/minute_hand"), CUCKOO_HOUR_HAND = block("cuckoo_clock/hour_hand"),
CUCKOO_LEFT_DOOR = block("cuckoo_clock/left_door"), CUCKOO_RIGHT_DOOR = block("cuckoo_clock/right_door"),

View file

@ -50,6 +50,7 @@ public class AllShapes {
.forDirectional(),
SAIL_FRAME = shape(0, 5, 0, 16, 9, 16).forDirectional(), SAIL = shape(0, 5, 0, 16, 10, 16).forDirectional(),
HARVESTER_BASE = shape(0, 2, 0, 16, 14, 3).forDirectional(SOUTH),
ROLLER_BASE = shape(0, 0, 0, 16, 16, 10).forDirectional(SOUTH),
NOZZLE = shape(2, 0, 2, 14, 14, 14).add(1, 13, 1, 15, 15, 15)
.erase(3, 13, 3, 13, 15, 13)
.forDirectional(),

View file

@ -4,6 +4,7 @@ import javax.annotation.ParametersAreNonnullByDefault;
import com.simibubi.create.AllShapes;
import com.simibubi.create.content.contraptions.wrench.IWrenchable;
import com.simibubi.create.foundation.block.ProperWaterloggedBlock;
import com.simibubi.create.foundation.utility.BlockHelper;
import net.minecraft.MethodsReturnNonnullByDefault;
@ -13,21 +14,25 @@ import net.minecraft.world.InteractionResult;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.HorizontalDirectionalBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition.Builder;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.pathfinder.PathComputationType;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
public abstract class AttachedActorBlock extends HorizontalDirectionalBlock implements IWrenchable {
public abstract class AttachedActorBlock extends HorizontalDirectionalBlock
implements IWrenchable, ProperWaterloggedBlock {
protected AttachedActorBlock(Properties p_i48377_1_) {
super(p_i48377_1_);
registerDefaultState(defaultBlockState().setValue(WATERLOGGED, false));
}
@Override
@ -43,7 +48,7 @@ public abstract class AttachedActorBlock extends HorizontalDirectionalBlock impl
@Override
protected void createBlockStateDefinition(Builder<Block, BlockState> builder) {
builder.add(FACING);
builder.add(FACING, WATERLOGGED);
super.createBlockStateDefinition(builder);
}
@ -57,22 +62,39 @@ public abstract class AttachedActorBlock extends HorizontalDirectionalBlock impl
@Override
public BlockState getStateForPlacement(BlockPlaceContext context) {
Direction facing;
if (context.getClickedFace().getAxis().isVertical())
facing = context.getHorizontalDirection().getOpposite();
if (context.getClickedFace()
.getAxis()
.isVertical())
facing = context.getHorizontalDirection()
.getOpposite();
else {
BlockState blockState =
context.getLevel().getBlockState(context.getClickedPos().relative(context.getClickedFace().getOpposite()));
BlockState blockState = context.getLevel()
.getBlockState(context.getClickedPos()
.relative(context.getClickedFace()
.getOpposite()));
if (blockState.getBlock() instanceof AttachedActorBlock)
facing = blockState.getValue(FACING);
else
facing = context.getClickedFace();
}
return defaultBlockState().setValue(FACING, facing);
return withWater(defaultBlockState().setValue(FACING, facing), context);
}
@Override
public BlockState updateShape(BlockState pState, Direction pDirection, BlockState pNeighborState,
LevelAccessor pLevel, BlockPos pCurrentPos, BlockPos pNeighborPos) {
updateWater(pLevel, pState, pCurrentPos);
return pState;
}
@Override
public boolean isPathfindable(BlockState state, BlockGetter reader, BlockPos pos, PathComputationType type) {
return false;
}
@Override
public FluidState getFluidState(BlockState pState) {
return fluidState(pState);
}
}

View file

@ -40,9 +40,9 @@ public class BlockBreakingMovementBehaviour implements MovementBehaviour {
damageEntities(context, pos, world);
if (world.isClientSide)
return;
if (!canBreak(world, pos, stateVisited))
return;
context.data.put("BreakingPos", NbtUtils.writeBlockPos(pos));
context.stall = true;
}
@ -180,7 +180,7 @@ public class BlockBreakingMovementBehaviour implements MovementBehaviour {
return;
}
float breakSpeed = Mth.clamp(Math.abs(context.getAnimationSpeed()) / 500f, 1 / 128f, 16f);
float breakSpeed = getBlockBreakingSpeed(context);
destroyProgress += Mth.clamp((int) (breakSpeed / blockHardness), 1, 10 - destroyProgress);
world.playSound(null, breakingPos, stateToBreak.getSoundType()
.getHitSound(), SoundSource.NEUTRAL, .25f, 1);
@ -199,7 +199,7 @@ public class BlockBreakingMovementBehaviour implements MovementBehaviour {
context.stall = false;
if (shouldDestroyStartBlock(stateToBreak))
BlockHelper.destroyBlock(context.world, breakingPos, 1f, stack -> this.dropItem(context, stack));
destroyBlock(context, breakingPos);
onBlockBroken(context, ogPos, stateToBreak);
ticksUntilNextProgress = -1;
data.remove("Progress");
@ -214,6 +214,14 @@ public class BlockBreakingMovementBehaviour implements MovementBehaviour {
data.putInt("Progress", destroyProgress);
}
protected void destroyBlock(MovementContext context, BlockPos breakingPos) {
BlockHelper.destroyBlock(context.world, breakingPos, 1f, stack -> this.dropItem(context, stack));
}
protected float getBlockBreakingSpeed(MovementContext context) {
return Mth.clamp(Math.abs(context.getAnimationSpeed()) / 500f, 1 / 128f, 16f);
}
protected boolean shouldDestroyStartBlock(BlockState stateToBreak) {
return true;
}

View file

@ -0,0 +1,76 @@
package com.simibubi.create.content.contraptions.components.actors;
import java.util.Arrays;
import java.util.function.Consumer;
import com.simibubi.create.foundation.gui.widget.Label;
import com.simibubi.create.foundation.gui.widget.ScrollInput;
import com.simibubi.create.foundation.gui.widget.SelectionScrollInput;
import com.simibubi.create.foundation.utility.Components;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.Pair;
import net.minecraft.client.Minecraft;
import net.minecraft.core.Direction;
import net.minecraft.world.entity.Entity;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
public enum DoorControl {
ALL, NORTH, EAST, SOUTH, WEST, NONE;
private static String[] valuesAsString() {
DoorControl[] values = values();
return Arrays.stream(values)
.map(dc -> Lang.asId(dc.name()))
.toList()
.toArray(new String[values.length]);
}
public boolean matches(Direction doorDirection) {
return switch (this) {
case ALL -> true;
case NORTH -> doorDirection == Direction.NORTH;
case EAST -> doorDirection == Direction.EAST;
case SOUTH -> doorDirection == Direction.SOUTH;
case WEST -> doorDirection == Direction.WEST;
default -> false;
};
}
@OnlyIn(Dist.CLIENT)
public static Pair<ScrollInput, Label> createWidget(int x, int y, Consumer<DoorControl> callback,
DoorControl initial) {
DoorControl playerFacing = NONE;
Entity cameraEntity = Minecraft.getInstance().cameraEntity;
if (cameraEntity != null) {
Direction direction = cameraEntity.getDirection();
if (direction == Direction.EAST)
playerFacing = EAST;
if (direction == Direction.WEST)
playerFacing = WEST;
if (direction == Direction.NORTH)
playerFacing = NORTH;
if (direction == Direction.SOUTH)
playerFacing = SOUTH;
}
Label label = new Label(x + 4, y + 6, Components.empty()).withShadow();
ScrollInput input = new SelectionScrollInput(x, y, 53, 16)
.forOptions(Lang.translatedOptions("contraption.door_control", valuesAsString()))
.titled(Lang.translateDirect("contraption.door_control"))
.calling(s -> {
DoorControl mode = values()[s];
label.text = Lang.translateDirect("contraption.door_control." + Lang.asId(mode.name()) + ".short");
callback.accept(mode);
})
.addHint(Lang.translateDirect("contraption.door_control.player_facing",
Lang.translateDirect("contraption.door_control." + Lang.asId(playerFacing.name()) + ".short")))
.setState(initial.ordinal());
input.onChanged();
return Pair.of(input, label);
}
}

View file

@ -0,0 +1,45 @@
package com.simibubi.create.content.contraptions.components.actors;
import com.simibubi.create.foundation.blockEntity.BlockEntityBehaviour;
import com.simibubi.create.foundation.blockEntity.SmartBlockEntity;
import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType;
import com.simibubi.create.foundation.utility.NBTHelper;
import net.minecraft.nbt.CompoundTag;
public class DoorControlBehaviour extends BlockEntityBehaviour {
public static final BehaviourType<DoorControlBehaviour> TYPE = new BehaviourType<>();
public DoorControl mode;
public DoorControlBehaviour(SmartBlockEntity be) {
super(be);
mode = DoorControl.ALL;
}
public void set(DoorControl mode) {
if (this.mode == mode)
return;
this.mode = mode;
blockEntity.notifyUpdate();
}
@Override
public void write(CompoundTag nbt, boolean clientPacket) {
NBTHelper.writeEnum(nbt, "DoorControl", mode);
super.write(nbt, clientPacket);
}
@Override
public void read(CompoundTag nbt, boolean clientPacket) {
mode = NBTHelper.readEnum(nbt, "DoorControl", DoorControl.class);
super.read(nbt, clientPacket);
}
@Override
public BehaviourType<?> getType() {
return TYPE;
}
}

View file

@ -3,6 +3,7 @@ package com.simibubi.create.content.contraptions.components.actors;
import com.jozufozu.flywheel.api.Material;
import com.jozufozu.flywheel.api.MaterialManager;
import com.jozufozu.flywheel.core.Materials;
import com.jozufozu.flywheel.core.PartialModel;
import com.jozufozu.flywheel.core.materials.model.ModelData;
import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld;
import com.simibubi.create.AllPartialModels;
@ -18,15 +19,13 @@ import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.phys.Vec3;
public class HarvesterActorInstance extends ActorInstance {
static double oneOverRadius = 16.0 / 6.5;
static float originOffset = 1 / 16f;
static Vec3 rotOffset = new Vec3(0.5f, -2 * originOffset + 0.5f, originOffset + 0.5f);
ModelData harvester;
private Direction facing;
private float horizontalAngle;
protected float horizontalAngle;
private double rotation;
private double previousRotation;
@ -41,13 +40,25 @@ public class HarvesterActorInstance extends ActorInstance {
facing = state.getValue(BlockStateProperties.HORIZONTAL_FACING);
harvester = material.getModel(AllPartialModels.HARVESTER_BLADE, state).createInstance();
harvester = material.getModel(getRollingPartial(), state).createInstance();
horizontalAngle = facing.toYRot() + ((facing.getAxis() == Direction.Axis.X) ? 180 : 0);
harvester.setBlockLight(localBlockLight());
}
protected PartialModel getRollingPartial() {
return AllPartialModels.HARVESTER_BLADE;
}
protected Vec3 getRotationOffset() {
return rotOffset;
}
protected double getRadius() {
return 6.5;
}
@Override
public void tick() {
super.tick();
@ -60,7 +71,7 @@ public class HarvesterActorInstance extends ActorInstance {
double arcLength = context.motion.length();
double radians = arcLength * oneOverRadius;
double radians = arcLength * 16 / getRadius();
float deg = AngleHelper.deg(radians);
@ -78,9 +89,9 @@ public class HarvesterActorInstance extends ActorInstance {
.centre()
.rotateY(horizontalAngle)
.unCentre()
.translate(rotOffset)
.translate(getRotationOffset())
.rotateX(getRotation())
.translateBack(rotOffset);
.translateBack(getRotationOffset());
}
private double getRotation() {

View file

@ -18,7 +18,6 @@ import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
@ -26,18 +25,18 @@ import net.minecraft.world.phys.Vec3;
public class HarvesterRenderer extends SafeBlockEntityRenderer<HarvesterBlockEntity> {
public HarvesterRenderer(BlockEntityRendererProvider.Context context) {
}
private static final Vec3 PIVOT = new Vec3(0, 6, 9);
public HarvesterRenderer(BlockEntityRendererProvider.Context context) {}
@Override
protected void renderSafe(HarvesterBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer,
int light, int overlay) {
BlockState blockState = be.getBlockState();
SuperByteBuffer superBuffer = CachedBufferer.partial(AllPartialModels.HARVESTER_BLADE, blockState);
transform(be.getLevel(), blockState.getValue(HarvesterBlock.FACING), superBuffer,
be.getAnimatedSpeed());
transform(be.getLevel(), blockState.getValue(HarvesterBlock.FACING), superBuffer, be.getAnimatedSpeed(), PIVOT);
superBuffer.light(light)
.renderInto(ms, buffer.getBuffer(RenderType.cutoutMipped()));
.renderInto(ms, buffer.getBuffer(RenderType.cutoutMipped()));
}
public static void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld,
@ -46,23 +45,22 @@ public class HarvesterRenderer extends SafeBlockEntityRenderer<HarvesterBlockEnt
Direction facing = blockState.getValue(HORIZONTAL_FACING);
SuperByteBuffer superBuffer = CachedBufferer.partial(AllPartialModels.HARVESTER_BLADE, blockState);
float speed = (float) (!VecHelper.isVecPointingTowards(context.relativeMotion, facing.getOpposite())
? context.getAnimationSpeed()
: 0);
? context.getAnimationSpeed()
: 0);
if (context.contraption.stalled)
speed = 0;
superBuffer.transform(matrices.getModel());
transform(context.world, facing, superBuffer, speed);
transform(context.world, facing, superBuffer, speed, PIVOT);
superBuffer
.light(matrices.getWorld(),
ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld))
.light(matrices.getWorld(), ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld))
.renderInto(matrices.getViewProjection(), buffers.getBuffer(RenderType.cutoutMipped()));
}
public static void transform(Level world, Direction facing, SuperByteBuffer superBuffer, float speed) {
public static void transform(Level world, Direction facing, SuperByteBuffer superBuffer, float speed, Vec3 pivot) {
float originOffset = 1 / 16f;
Vec3 rotOffset = new Vec3(0, -2 * originOffset, originOffset).add(VecHelper.getCenterOf(BlockPos.ZERO));
Vec3 rotOffset = new Vec3(0, pivot.y * originOffset, pivot.z * originOffset);
float time = AnimationTickHolder.getRenderTime(world) / 20;
float angle = (time * speed) % 360;

View file

@ -0,0 +1,56 @@
package com.simibubi.create.content.contraptions.components.actors;
import com.jozufozu.flywheel.api.Material;
import com.jozufozu.flywheel.api.MaterialManager;
import com.jozufozu.flywheel.core.Materials;
import com.jozufozu.flywheel.core.PartialModel;
import com.jozufozu.flywheel.core.materials.model.ModelData;
import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld;
import com.simibubi.create.AllPartialModels;
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
import net.minecraft.world.phys.Vec3;
public class RollerActorInstance extends HarvesterActorInstance {
static Vec3 rotOffset = new Vec3(0.5f, -12 * originOffset + 0.5f, 8 * originOffset + 0.5f);
ModelData frame;
public RollerActorInstance(MaterialManager materialManager, VirtualRenderWorld simulationWorld,
MovementContext context) {
super(materialManager, simulationWorld, context);
Material<ModelData> material = materialManager.defaultCutout()
.material(Materials.TRANSFORMED);
frame = material.getModel(AllPartialModels.ROLLER_FRAME, context.state)
.createInstance();
frame.setBlockLight(localBlockLight());
}
@Override
public void beginFrame() {
super.beginFrame();
frame.loadIdentity()
.translate(context.localPos)
.centre()
.rotateY(horizontalAngle)
.unCentre();
}
@Override
protected PartialModel getRollingPartial() {
return AllPartialModels.ROLLER_WHEEL;
}
@Override
protected Vec3 getRotationOffset() {
return rotOffset;
}
@Override
protected double getRadius() {
return 16.5;
}
}

View file

@ -0,0 +1,53 @@
package com.simibubi.create.content.contraptions.components.actors;
import com.simibubi.create.AllBlockEntityTypes;
import com.simibubi.create.AllShapes;
import com.simibubi.create.foundation.block.IBE;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
public class RollerBlock extends AttachedActorBlock implements IBE<RollerBlockEntity> {
public static DamageSource damageSourceRoller = new DamageSource("create.mechanical_roller");
public RollerBlock(Properties p_i48377_1_) {
super(p_i48377_1_);
}
@Override
public BlockState getStateForPlacement(BlockPlaceContext context) {
return withWater(defaultBlockState().setValue(FACING, context.getHorizontalDirection()
.getOpposite()), context);
}
@Override
public Class<RollerBlockEntity> getBlockEntityClass() {
return RollerBlockEntity.class;
}
@Override
public BlockEntityType<? extends RollerBlockEntity> getBlockEntityType() {
return AllBlockEntityTypes.MECHANICAL_ROLLER.get();
}
@Override
public VoxelShape getShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) {
Direction direction = state.getValue(FACING);
return AllShapes.ROLLER_BASE.get(direction);
}
@Override
public boolean canSurvive(BlockState state, LevelReader worldIn, BlockPos pos) {
return true;
}
}

View file

@ -0,0 +1,138 @@
package com.simibubi.create.content.contraptions.components.actors;
import java.util.List;
import com.jozufozu.flywheel.util.transform.TransformStack;
import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.foundation.blockEntity.BlockEntityBehaviour;
import com.simibubi.create.foundation.blockEntity.SmartBlockEntity;
import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform;
import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour;
import com.simibubi.create.foundation.blockEntity.behaviour.scrollvalue.INamedIconOptions;
import com.simibubi.create.foundation.blockEntity.behaviour.scrollvalue.ScrollOptionBehaviour;
import com.simibubi.create.foundation.gui.AllIcons;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Direction.Axis;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.EntityBlock;
import net.minecraft.world.level.block.StairBlock;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
public class RollerBlockEntity extends SmartBlockEntity {
// For simulations such as Ponder
private float manuallyAnimatedSpeed;
public FilteringBehaviour filtering;
public ScrollOptionBehaviour<RollingMode> mode;
public RollerBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
super(type, pos, state);
}
@Override
public void addBehaviours(List<BlockEntityBehaviour> behaviours) {
behaviours.add(filtering = new FilteringBehaviour(this, new RollerValueBox(4)).moveText(new Vec3(-30, 23, 10))
.withCallback(this::onFilterChanged));
behaviours.add(mode = new ScrollOptionBehaviour<RollingMode>(RollingMode.class,
Lang.translateDirect("contraptions.roller_mode"), this, new RollerValueBox(-2)));
}
protected boolean onFilterChanged(ItemStack newFilter) {
BlockState appliedState = RollerMovementBehaviour.getStateToPaveWith(newFilter);
if (appliedState.isAir())
return false;
if (appliedState.getBlock() instanceof EntityBlock)
return false;
if (appliedState.getBlock() instanceof StairBlock)
return false;
VoxelShape shape = appliedState.getShape(level, worldPosition);
if (shape.isEmpty() || !shape.bounds()
.equals(Shapes.block()
.bounds()))
return false;
VoxelShape collisionShape = appliedState.getCollisionShape(level, worldPosition);
if (collisionShape.isEmpty())
return false;
return true;
}
@Override
protected AABB createRenderBoundingBox() {
return new AABB(worldPosition).inflate(1);
}
public float getAnimatedSpeed() {
return manuallyAnimatedSpeed;
}
public void setAnimatedSpeed(float speed) {
manuallyAnimatedSpeed = speed;
}
static enum RollingMode implements INamedIconOptions {
TUNNEL_PAVE(AllIcons.I_ROLLER_PAVE),
STRAIGHT_FILL(AllIcons.I_ROLLER_FILL),
WIDE_FILL(AllIcons.I_ROLLER_WIDE_FILL),
;
private String translationKey;
private AllIcons icon;
private RollingMode(AllIcons icon) {
this.icon = icon;
translationKey = "contraptions.roller_mode." + Lang.asId(name());
}
@Override
public AllIcons getIcon() {
return icon;
}
@Override
public String getTranslationKey() {
return translationKey;
}
}
private final class RollerValueBox extends ValueBoxTransform {
private int hOffset;
public RollerValueBox(int hOffset) {
this.hOffset = hOffset;
}
@Override
protected void rotate(BlockState state, PoseStack ms) {
Direction facing = state.getValue(RollerBlock.FACING);
float yRot = AngleHelper.horizontalAngle(facing) + 180;
TransformStack.cast(ms)
.rotateY(yRot)
.rotateX(90);
}
@Override
protected Vec3 getLocalOffset(BlockState state) {
Direction facing = state.getValue(RollerBlock.FACING);
float stateAngle = AngleHelper.horizontalAngle(facing) + 180;
return VecHelper.rotateCentered(VecHelper.voxelSpace(7.75 + hOffset, 15.5f, 11), stateAngle, Axis.Y);
}
}
}

View file

@ -0,0 +1,452 @@
package com.simibubi.create.content.contraptions.components.actors;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.function.BiConsumer;
import javax.annotation.Nullable;
import com.jozufozu.flywheel.api.MaterialManager;
import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.components.actors.RollerBlockEntity.RollingMode;
import com.simibubi.create.content.contraptions.components.actors.trackPaver.PaveTask;
import com.simibubi.create.content.contraptions.components.actors.trackPaver.TrackPaverV2;
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyContraption;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher;
import com.simibubi.create.content.logistics.item.filter.FilterItem;
import com.simibubi.create.content.logistics.trains.TrackEdge;
import com.simibubi.create.content.logistics.trains.TrackGraph;
import com.simibubi.create.content.logistics.trains.entity.Carriage;
import com.simibubi.create.content.logistics.trains.entity.CarriageBogey;
import com.simibubi.create.content.logistics.trains.entity.CarriageContraptionEntity;
import com.simibubi.create.content.logistics.trains.entity.Train;
import com.simibubi.create.content.logistics.trains.entity.TravellingPoint;
import com.simibubi.create.content.logistics.trains.entity.TravellingPoint.ITrackSelector;
import com.simibubi.create.content.logistics.trains.entity.TravellingPoint.SteerDirection;
import com.simibubi.create.content.logistics.trains.track.StandardBogeyBlock;
import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.item.ItemHelper;
import com.simibubi.create.foundation.utility.BlockHelper;
import com.simibubi.create.foundation.utility.Couple;
import com.simibubi.create.foundation.utility.Pair;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Direction.Axis;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.BlockTags;
import net.minecraft.util.Mth;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.FallingBlock;
import net.minecraft.world.level.block.SlabBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.SlabType;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.registries.ForgeRegistries;
public class RollerMovementBehaviour extends BlockBreakingMovementBehaviour {
@Override
public boolean isActive(MovementContext context) {
return super.isActive(context) && !(context.contraption instanceof PulleyContraption)
&& VecHelper.isVecPointingTowards(context.relativeMotion, context.state.getValue(RollerBlock.FACING));
}
@Override
public boolean hasSpecialInstancedRendering() {
return true;
}
@Nullable
@Override
public ActorInstance createInstance(MaterialManager materialManager, VirtualRenderWorld simulationWorld,
MovementContext context) {
return new RollerActorInstance(materialManager, simulationWorld, context);
}
@Override
public void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld,
ContraptionMatrices matrices, MultiBufferSource buffers) {
if (!ContraptionRenderDispatcher.canInstance())
RollerRenderer.renderInContraption(context, renderWorld, matrices, buffers);
}
@Override
public Vec3 getActiveAreaOffset(MovementContext context) {
return Vec3.atLowerCornerOf(context.state.getValue(RollerBlock.FACING)
.getNormal())
.scale(.45)
.subtract(0, 2, 0);
}
@Override
protected float getBlockBreakingSpeed(MovementContext context) {
return Mth.clamp(super.getBlockBreakingSpeed(context) * 4, 1 / 128f, 16f);
}
@Override
public boolean canBreak(Level world, BlockPos breakingPos, BlockState state) {
return super.canBreak(world, breakingPos, state) && !state.getCollisionShape(world, breakingPos)
.isEmpty() && !AllBlocks.TRACK.has(state);
}
@Override
protected DamageSource getDamageSource() {
return RollerBlock.damageSourceRoller;
}
@Override
public void visitNewPosition(MovementContext context, BlockPos pos) {
Level world = context.world;
BlockState stateVisited = world.getBlockState(pos);
if (!stateVisited.isRedstoneConductor(world, pos))
damageEntities(context, pos, world);
if (world.isClientSide)
return;
List<BlockPos> positionsToBreak = getPositionsToBreak(context, pos);
if (positionsToBreak.isEmpty()) {
triggerPaver(context, pos);
return;
}
BlockPos argMax = null;
double max = Double.MIN_VALUE;
for (BlockPos toBreak : positionsToBreak) {
float hardness = context.world.getBlockState(toBreak)
.getDestroySpeed(world, toBreak);
if (hardness < max)
continue;
max = hardness;
argMax = toBreak;
}
context.data.put("ReferencePos", NbtUtils.writeBlockPos(pos));
context.data.put("BreakingPos", NbtUtils.writeBlockPos(argMax));
context.stall = true;
}
@Override
protected void onBlockBroken(MovementContext context, BlockPos pos, BlockState brokenState) {
super.onBlockBroken(context, pos, brokenState);
if (!context.data.contains("ReferencePos"))
return;
BlockPos referencePos = NbtUtils.readBlockPos(context.data.getCompound("ReferencePos"));
for (BlockPos otherPos : getPositionsToBreak(context, referencePos))
if (!otherPos.equals(pos))
destroyBlock(context, otherPos);
triggerPaver(context, referencePos);
context.data.remove("ReferencePos");
}
@Override
protected void destroyBlock(MovementContext context, BlockPos breakingPos) {
BlockState blockState = context.world.getBlockState(breakingPos);
boolean noHarvest = blockState.is(BlockTags.NEEDS_IRON_TOOL) || blockState.is(BlockTags.NEEDS_STONE_TOOL)
|| blockState.is(BlockTags.NEEDS_DIAMOND_TOOL);
BlockHelper.destroyBlock(context.world, breakingPos, 1f, stack -> {
if (noHarvest || context.world.random.nextBoolean())
return;
this.dropItem(context, stack);
});
super.destroyBlock(context, breakingPos);
}
RollerTravellingPoint rollerScout = new RollerTravellingPoint();
protected List<BlockPos> getPositionsToBreak(MovementContext context, BlockPos visitedPos) {
ArrayList<BlockPos> positions = new ArrayList<>();
RollingMode mode = getMode(context);
if (mode != RollingMode.TUNNEL_PAVE)
return positions;
// Train
PaveTask profileForTracks = createHeightProfileForTracks(context);
if (profileForTracks != null) {
for (Couple<Integer> coords : profileForTracks.keys()) {
float height = profileForTracks.get(coords);
BlockPos targetPosition = new BlockPos(coords.getFirst(), height, coords.getSecond());
boolean shouldPlaceSlab = height > Math.floor(height) + .45;
for (int i = 0; i <= (shouldPlaceSlab ? 3 : 2); i++)
if (testBreakerTarget(context, targetPosition.above(i), i))
positions.add(targetPosition.above(i));
}
return positions;
}
// Otherwise
for (int i = 0; i <= 2; i++)
if (testBreakerTarget(context, visitedPos.above(i), i))
positions.add(visitedPos.above(i));
return positions;
}
protected boolean testBreakerTarget(MovementContext context, BlockPos target, int columnY) {
BlockState stateToPaveWith = getStateToPaveWith(context);
BlockState stateToPaveWithAsSlab = getStateToPaveWithAsSlab(context);
BlockState stateAbove = context.world.getBlockState(target);
if (columnY == 0 && stateAbove.is(stateToPaveWith.getBlock()))
return false;
if (stateToPaveWithAsSlab != null && columnY == 1 && stateAbove.is(stateToPaveWithAsSlab.getBlock()))
return false;
return canBreak(context.world, target, stateAbove);
}
@Nullable
protected PaveTask createHeightProfileForTracks(MovementContext context) {
if (context.contraption == null)
return null;
if (!(context.contraption.entity instanceof CarriageContraptionEntity cce))
return null;
Carriage carriage = cce.getCarriage();
if (carriage == null)
return null;
Train train = carriage.train;
if (train == null || train.graph == null)
return null;
CarriageBogey mainBogey = carriage.bogeys.getFirst();
TravellingPoint point = mainBogey.trailing();
rollerScout.node1 = point.node1;
rollerScout.node2 = point.node2;
rollerScout.edge = point.edge;
rollerScout.position = point.position;
Axis axis = Axis.X;
StructureBlockInfo info = context.contraption.getBlocks()
.get(BlockPos.ZERO);
if (info != null && info.state.hasProperty(StandardBogeyBlock.AXIS))
axis = info.state.getValue(StandardBogeyBlock.AXIS);
Direction orientation = cce.getInitialOrientation();
Direction rollerFacing = context.state.getValue(RollerBlock.FACING);
int step = orientation.getAxisDirection()
.getStep();
double widthWiseOffset = axis.choose(-context.localPos.getZ(), 0, -context.localPos.getX()) * step;
double lengthWiseOffset = axis.choose(-context.localPos.getX(), 0, context.localPos.getZ()) * step - 1;
if (rollerFacing == orientation.getClockWise())
lengthWiseOffset += 1;
double distanceToTravel = 2;
PaveTask heightProfile = new PaveTask(widthWiseOffset, widthWiseOffset);
ITrackSelector steering = rollerScout.steer(SteerDirection.NONE, new Vec3(0, 1, 0));
rollerScout.traversalCallback = (edge, coords) -> {
};
rollerScout.travel(train.graph, lengthWiseOffset + 1, steering);
rollerScout.traversalCallback =
(edge, coords) -> TrackPaverV2.pave(heightProfile, edge, coords.getFirst(), coords.getSecond());
rollerScout.travel(train.graph, distanceToTravel, steering);
for (Couple<Integer> entry : heightProfile.keys())
heightProfile.put(entry.getFirst(), entry.getSecond(), context.localPos.getY() + heightProfile.get(entry));
return heightProfile;
}
protected void triggerPaver(MovementContext context, BlockPos pos) {
BlockState stateToPaveWith = getStateToPaveWith(context);
BlockState stateToPaveWithAsSlab = getStateToPaveWithAsSlab(context);
RollingMode mode = getMode(context);
Vec3 directionVec = Vec3.atLowerCornerOf(context.state.getValue(RollerBlock.FACING)
.getClockWise()
.getNormal());
directionVec = context.rotation.apply(directionVec);
PaveResult paveResult = PaveResult.PASS;
int yOffset = 0;
List<Pair<BlockPos, Boolean>> paveSet = new ArrayList<>();
PaveTask profileForTracks = createHeightProfileForTracks(context);
if (profileForTracks == null)
paveSet.add(Pair.of(pos, false));
else
for (Couple<Integer> coords : profileForTracks.keys()) {
float height = profileForTracks.get(coords);
boolean shouldPlaceSlab = height > Math.floor(height) + .45;
BlockPos targetPosition = new BlockPos(coords.getFirst(), height, coords.getSecond());
paveSet.add(Pair.of(targetPosition, shouldPlaceSlab));
}
if (paveSet.isEmpty())
return;
while (paveResult == PaveResult.PASS) {
if (yOffset > AllConfigs.server().kinetics.rollerFillDepth.get()) {
paveResult = PaveResult.FAIL;
break;
}
Set<Pair<BlockPos, Boolean>> currentLayer = new HashSet<>();
if (mode == RollingMode.WIDE_FILL) {
for (Pair<BlockPos, Boolean> anchor : paveSet) {
int radius = (yOffset + 1) / 2;
for (int i = -radius; i <= radius; i++)
for (int j = -radius; j <= radius; j++)
if (BlockPos.ZERO.distManhattan(new BlockPos(i, 0, j)) <= radius)
currentLayer.add(Pair.of(anchor.getFirst()
.offset(i, -yOffset, j), anchor.getSecond()));
}
} else
for (Pair<BlockPos, Boolean> anchor : paveSet)
currentLayer.add(Pair.of(anchor.getFirst()
.below(yOffset), anchor.getSecond()));
boolean completelyBlocked = true;
boolean anyBlockPlaced = false;
for (Pair<BlockPos, Boolean> currentPos : currentLayer) {
if (stateToPaveWithAsSlab != null && yOffset == 0 && currentPos.getSecond())
tryFill(context, currentPos.getFirst()
.above(), stateToPaveWithAsSlab);
paveResult = tryFill(context, currentPos.getFirst(), stateToPaveWith);
if (paveResult != PaveResult.FAIL)
completelyBlocked = false;
if (paveResult == PaveResult.SUCCESS)
anyBlockPlaced = true;
}
if (anyBlockPlaced)
paveResult = PaveResult.SUCCESS;
else if (!completelyBlocked || yOffset == 0)
paveResult = PaveResult.PASS;
if (paveResult == PaveResult.SUCCESS && stateToPaveWith.getBlock() instanceof FallingBlock)
paveResult = PaveResult.PASS;
if (paveResult != PaveResult.PASS)
break;
if (mode == RollingMode.TUNNEL_PAVE)
break;
yOffset++;
}
if (paveResult == PaveResult.SUCCESS) {
context.data.putInt("WaitingTicks", 2);
context.data.put("LastPos", NbtUtils.writeBlockPos(pos));
context.stall = true;
}
}
public static BlockState getStateToPaveWith(ItemStack itemStack) {
if (itemStack.getItem()instanceof BlockItem bi) {
BlockState defaultBlockState = bi.getBlock()
.defaultBlockState();
if (defaultBlockState.hasProperty(SlabBlock.TYPE))
defaultBlockState = defaultBlockState.setValue(SlabBlock.TYPE, SlabType.DOUBLE);
return defaultBlockState;
}
return Blocks.AIR.defaultBlockState();
}
protected BlockState getStateToPaveWith(MovementContext context) {
return getStateToPaveWith(ItemStack.of(context.blockEntityData.getCompound("Filter")));
}
protected BlockState getStateToPaveWithAsSlab(MovementContext context) {
BlockState stateToPaveWith = getStateToPaveWith(context);
if (stateToPaveWith.hasProperty(SlabBlock.TYPE))
return stateToPaveWith.setValue(SlabBlock.TYPE, SlabType.BOTTOM);
Block block = stateToPaveWith.getBlock();
if (block == null)
return null;
ResourceLocation rl = block.getRegistryName();
String namespace = rl.getNamespace();
String blockName = rl.getPath();
int nameLength = blockName.length();
List<String> possibleSlabLocations = new ArrayList<>();
possibleSlabLocations.add(blockName + "_slab");
if (blockName.endsWith("s") && nameLength > 1)
possibleSlabLocations.add(blockName.substring(0, nameLength - 1) + "_slab");
if (blockName.endsWith("planks") && nameLength > 7)
possibleSlabLocations.add(blockName.substring(0, nameLength - 7) + "_slab");
for (String locationAttempt : possibleSlabLocations) {
Optional<Block> result = ForgeRegistries.BLOCKS.getHolder(new ResourceLocation(namespace, locationAttempt))
.map(slabHolder -> slabHolder.value());
if (result.isEmpty())
continue;
return result.get()
.defaultBlockState();
}
return null;
}
protected RollingMode getMode(MovementContext context) {
return RollingMode.values()[context.blockEntityData.getInt("ScrollValue")];
}
private final class RollerTravellingPoint extends TravellingPoint {
public BiConsumer<TrackEdge, Couple<Double>> traversalCallback;
@Override
protected Double edgeTraversedFrom(TrackGraph graph, boolean forward, IEdgePointListener edgePointListener,
ITurnListener turnListener, double prevPos, double totalDistance) {
double from = forward ? prevPos : position;
double to = forward ? position : prevPos;
traversalCallback.accept(edge, Couple.create(from, to));
return super.edgeTraversedFrom(graph, forward, edgePointListener, turnListener, prevPos, totalDistance);
}
}
private enum PaveResult {
FAIL, PASS, SUCCESS;
}
protected PaveResult tryFill(MovementContext context, BlockPos targetPos, BlockState toPlace) {
Level level = context.world;
if (!level.isLoaded(targetPos))
return PaveResult.FAIL;
BlockState existing = level.getBlockState(targetPos);
if (existing.is(toPlace.getBlock()))
return PaveResult.PASS;
if (!existing.is(BlockTags.LEAVES) && !existing.getMaterial()
.isReplaceable()
&& !existing.getCollisionShape(level, targetPos)
.isEmpty())
return PaveResult.FAIL;
ItemStack filter = ItemStack.of(context.blockEntityData.getCompound("Filter"));
ItemStack held = ItemHelper.extract(context.contraption.getSharedInventory(),
stack -> FilterItem.test(context.world, stack, filter), 1, false);
if (held.isEmpty())
return PaveResult.FAIL;
level.setBlockAndUpdate(targetPos, toPlace);
return PaveResult.SUCCESS;
}
}

View file

@ -0,0 +1,85 @@
package com.simibubi.create.content.contraptions.components.actors;
import static net.minecraft.world.level.block.state.properties.BlockStateProperties.HORIZONTAL_FACING;
import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld;
import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.AllPartialModels;
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher;
import com.simibubi.create.foundation.blockEntity.renderer.SmartBlockEntityRenderer;
import com.simibubi.create.foundation.render.CachedBufferer;
import com.simibubi.create.foundation.render.SuperByteBuffer;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider.Context;
import net.minecraft.core.Direction;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.Vec3;
public class RollerRenderer extends SmartBlockEntityRenderer<RollerBlockEntity> {
private static final Vec3 PIVOT = new Vec3(0, -4, 16);
public RollerRenderer(Context context) {
super(context);
}
@Override
protected void renderSafe(RollerBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer,
int light, int overlay) {
super.renderSafe(be, partialTicks, ms, buffer, light, overlay);
BlockState blockState = be.getBlockState();
ms.pushPose();
ms.translate(0, -.25, 0);
SuperByteBuffer superBuffer = CachedBufferer.partial(AllPartialModels.ROLLER_WHEEL, blockState)
.translate(0, .25, 0);
Direction facing = blockState.getValue(RollerBlock.FACING);
HarvesterRenderer.transform(be.getLevel(), facing, superBuffer, be.getAnimatedSpeed(), PIVOT);
superBuffer.light(light)
.renderInto(ms, buffer.getBuffer(RenderType.cutoutMipped()));
ms.popPose();
CachedBufferer.partial(AllPartialModels.ROLLER_FRAME, blockState)
.rotateCentered(Direction.UP, AngleHelper.rad(AngleHelper.horizontalAngle(facing)))
.light(light)
.renderInto(ms, buffer.getBuffer(RenderType.solid()));
}
public static void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld,
ContraptionMatrices matrices, MultiBufferSource buffers) {
BlockState blockState = context.state;
Direction facing = blockState.getValue(HORIZONTAL_FACING);
SuperByteBuffer superBuffer = CachedBufferer.partial(AllPartialModels.ROLLER_WHEEL, blockState);
float speed = (float) (!VecHelper.isVecPointingTowards(context.relativeMotion, facing.getOpposite())
? context.getAnimationSpeed()
: -context.getAnimationSpeed());
if (context.contraption.stalled)
speed = 0;
superBuffer.translate(0, .25, 0)
.transform(matrices.getModel());
HarvesterRenderer.transform(context.world, facing, superBuffer, speed, PIVOT);
PoseStack viewProjection = matrices.getViewProjection();
viewProjection.pushPose();
viewProjection.translate(0, -.25, 0);
int contraptionWorldLight = ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld);
superBuffer.light(matrices.getWorld(), contraptionWorldLight)
.renderInto(viewProjection, buffers.getBuffer(RenderType.cutoutMipped()));
viewProjection.popPose();
CachedBufferer.partial(AllPartialModels.ROLLER_FRAME, blockState)
.transform(matrices.getModel())
.rotateCentered(Direction.UP, AngleHelper.rad(AngleHelper.horizontalAngle(facing)))
.light(matrices.getWorld(), contraptionWorldLight)
.renderInto(viewProjection, buffers.getBuffer(RenderType.solid()));
}
}

View file

@ -2,7 +2,6 @@ package com.simibubi.create.content.contraptions.components.actors.controls;
import java.util.Iterator;
import java.util.List;
import java.util.function.Supplier;
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
@ -40,35 +39,32 @@ public class ContraptionDisableActorPacket extends SimplePacketBase {
}
@Override
public void handle(Supplier<Context> context) {
context.get()
.enqueueWork(() -> {
Entity entityByID = Minecraft.getInstance().level.getEntity(entityID);
if (!(entityByID instanceof AbstractContraptionEntity ace))
return;
Contraption contraption = ace.getContraption();
List<ItemStack> disabledActors = contraption.getDisabledActors();
if (filter.isEmpty())
disabledActors.clear();
if (!enable) {
disabledActors.add(filter);
contraption.setActorsActive(filter, false);
return;
}
public boolean handle(Context context) {
context.enqueueWork(() -> {
Entity entityByID = Minecraft.getInstance().level.getEntity(entityID);
if (!(entityByID instanceof AbstractContraptionEntity ace))
return;
Contraption contraption = ace.getContraption();
List<ItemStack> disabledActors = contraption.getDisabledActors();
if (filter.isEmpty())
disabledActors.clear();
if (!enable) {
disabledActors.add(filter);
contraption.setActorsActive(filter, false);
return;
}
for (Iterator<ItemStack> iterator = disabledActors.iterator(); iterator.hasNext();) {
ItemStack next = iterator.next();
if (ContraptionControlsMovement.isSameFilter(next, filter) || next.isEmpty())
iterator.remove();
}
contraption.setActorsActive(filter, true);
});
context.get()
.setPacketHandled(true);
for (Iterator<ItemStack> iterator = disabledActors.iterator(); iterator.hasNext();) {
ItemStack next = iterator.next();
if (ContraptionControlsMovement.isSameFilter(next, filter) || next.isEmpty())
iterator.remove();
}
contraption.setActorsActive(filter, true);
});
return true;
}
}

View file

@ -0,0 +1,40 @@
package com.simibubi.create.content.contraptions.components.actors.trackPaver;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import com.simibubi.create.foundation.utility.Couple;
import net.minecraft.core.BlockPos;
public class PaveTask {
private Couple<Double> horizontalInterval;
private Map<Couple<Integer>, Float> heightValues = new HashMap<>();
public PaveTask(double h1, double h2) {
horizontalInterval = Couple.create(h1, h2);
}
public Couple<Double> getHorizontalInterval() {
return horizontalInterval;
}
public void put(int x, int z, float y) {
heightValues.put(Couple.create(x, z), y);
}
public float get(Couple<Integer> coords) {
return heightValues.get(coords);
}
public Set<Couple<Integer>> keys() {
return heightValues.keySet();
}
public void put(BlockPos p) {
put(p.getX(), p.getZ(), p.getY());
}
}

View file

@ -0,0 +1,215 @@
package com.simibubi.create.content.contraptions.components.actors.trackPaver;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import com.simibubi.create.content.logistics.trains.BezierConnection;
import com.simibubi.create.content.logistics.trains.TrackEdge;
import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.Pair;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.core.BlockPos;
import net.minecraft.util.Mth;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec2;
import net.minecraft.world.phys.Vec3;
public class TrackPaverV2 {
public static void pave(PaveTask task, TrackEdge edge, double from, double to) {
if (edge.isTurn()) {
paveCurve(task, edge.getTurn(), from, to);
return;
}
Vec3 location1 = edge.node1.getLocation()
.getLocation();
Vec3 location2 = edge.node2.getLocation()
.getLocation();
Vec3 diff = location2.subtract(location1);
Vec3 direction = VecHelper.clampComponentWise(diff, 1);
int extent = (int) Math.round((to - from) / direction.length());
double length = edge.getLength();
BlockPos pos = new BlockPos(edge.getPosition(Mth.clamp(from, 1 / 16f, length - 1 / 16f) / length)
.subtract(0, 0.5, 0));
paveStraight(task, pos, direction, extent);
}
public static void paveStraight(PaveTask task, BlockPos startPos, Vec3 direction, int extent) {
Set<BlockPos> toPlaceOn = new HashSet<>();
Vec3 start = VecHelper.getCenterOf(startPos);
Vec3 mainNormal = direction.cross(new Vec3(0, 1, 0));
Vec3 normalizedDirection = direction.normalize();
boolean isDiagonalTrack = direction.multiply(1, 0, 1)
.length() > 1.125f;
double r1 = task.getHorizontalInterval()
.getFirst();
int flip = (int) Math.signum(r1);
double r2 = r1 + flip;
if (isDiagonalTrack) {
r1 /= Mth.SQRT_OF_TWO;
r2 /= Mth.SQRT_OF_TWO;
}
int currentOffset = (int) (Math.abs(r1) * 2 + .5f);
int nextOffset = (int) (Math.abs(r2) * 2 + .5f);
for (int i = 0; i < extent; i++) {
Vec3 offset = direction.scale(i);
Vec3 mainPos = start.add(offset.x, offset.y, offset.z);
Vec3 targetVec = mainPos.add(mainNormal.scale(flip * (int) (currentOffset / 2.0)));
if (!isDiagonalTrack) {
toPlaceOn.add(new BlockPos(targetVec));
continue;
}
boolean placeRow = currentOffset % 2 == 0 || nextOffset % 2 == 1;
boolean placeSides = currentOffset % 2 == 1 || nextOffset % 2 == 0;
if (placeSides) {
for (int side : Iterate.positiveAndNegative) {
Vec3 sideOffset = normalizedDirection.scale(side)
.add(mainNormal.normalize()
.scale(flip))
.scale(.5);
toPlaceOn.add(new BlockPos(targetVec.add(sideOffset)));
}
}
if (placeRow) {
if (Math.abs(currentOffset % 2) == 1)
targetVec = mainPos.add(mainNormal.scale(flip * (int) ((currentOffset + 1) / 2.0)));
toPlaceOn.add(new BlockPos(targetVec));
}
}
toPlaceOn.forEach(task::put);
}
public static void paveCurve(PaveTask task, BezierConnection bc, double from, double to) {
Map<Pair<Integer, Integer>, Double> yLevels = new HashMap<>();
Map<Pair<Integer, Integer>, Double> tLevels = new HashMap<>();
BlockPos tePosition = bc.tePositions.getFirst();
double radius = -task.getHorizontalInterval()
.getFirst();
double r1 = radius - .575;
double r2 = radius + .575;
double handleLength = bc.getHandleLength();
Vec3 start = bc.starts.getFirst()
.subtract(Vec3.atLowerCornerOf(tePosition))
.add(0, 3 / 16f, 0);
Vec3 end = bc.starts.getSecond()
.subtract(Vec3.atLowerCornerOf(tePosition))
.add(0, 3 / 16f, 0);
Vec3 startHandle = bc.axes.getFirst()
.scale(handleLength)
.add(start);
Vec3 endHandle = bc.axes.getSecond()
.scale(handleLength)
.add(end);
Vec3 startNormal = bc.normals.getFirst();
Vec3 endNormal = bc.normals.getSecond();
int segCount = bc.getSegmentCount();
float[] lut = bc.getStepLUT();
double localFrom = from / bc.getLength();
double localTo = to / bc.getLength();
for (int i = 0; i < segCount; i++) {
float t = i == segCount ? 1 : i * lut[i] / segCount;
float t1 = (i + 1) == segCount ? 1 : (i + 1) * lut[(i + 1)] / segCount;
if (t1 < localFrom)
continue;
if (t > localTo)
continue;
Vec3 vt = VecHelper.bezier(start, end, startHandle, endHandle, t);
Vec3 vNormal = startNormal.equals(endNormal) ? startNormal : VecHelper.slerp(t, startNormal, endNormal);
Vec3 hNormal = vNormal.cross(VecHelper.bezierDerivative(start, end, startHandle, endHandle, t)
.normalize())
.normalize();
vt = vt.add(vNormal.scale(-1.175f));
Vec3 vt1 = VecHelper.bezier(start, end, startHandle, endHandle, t1);
Vec3 vNormal1 = startNormal.equals(endNormal) ? startNormal : VecHelper.slerp(t1, startNormal, endNormal);
Vec3 hNormal1 = vNormal1.cross(VecHelper.bezierDerivative(start, end, startHandle, endHandle, t1)
.normalize())
.normalize();
vt1 = vt1.add(vNormal1.scale(-1.175f));
Vec3 a3 = vt.add(hNormal.scale(r2));
Vec3 b3 = vt1.add(hNormal1.scale(r2));
Vec3 c3 = vt1.add(hNormal1.scale(r1));
Vec3 d3 = vt.add(hNormal.scale(r1));
Vec2 a = vec2(a3);
Vec2 b = vec2(b3);
Vec2 c = vec2(c3);
Vec2 d = vec2(d3);
AABB aabb = new AABB(a3, b3).minmax(new AABB(c3, d3));
double y = vt.add(vt1).y / 2f;
for (int scanX = Mth.floor(aabb.minX); scanX <= aabb.maxX; scanX++) {
for (int scanZ = Mth.floor(aabb.minZ); scanZ <= aabb.maxZ; scanZ++) {
Vec2 p = new Vec2(scanX + .5f, scanZ + .5f);
if (!isInTriangle(a, b, c, p) && !isInTriangle(a, c, d, p))
continue;
Pair<Integer, Integer> key = Pair.of(scanX, scanZ);
if (!yLevels.containsKey(key) || yLevels.get(key) > y) {
yLevels.put(key, y);
tLevels.put(key, (t + t1) / 2d);
}
}
}
}
//
for (Entry<Pair<Integer, Integer>, Double> entry : yLevels.entrySet()) {
double yValue = entry.getValue();
int floor = Mth.floor(yValue);
BlockPos targetPos = new BlockPos(entry.getKey()
.getFirst(), floor,
entry.getKey()
.getSecond()).offset(tePosition);
task.put(targetPos.getX(), targetPos.getZ(), targetPos.getY() + (yValue - floor >= .5 ? .5f : 0));
}
}
private static Vec2 vec2(Vec3 vec3) {
return new Vec2((float) vec3.x, (float) vec3.z);
}
private static boolean isInTriangle(Vec2 a, Vec2 b, Vec2 c, Vec2 p) {
float pcx = p.x - c.x;
float pcy = p.y - c.y;
float cbx = c.x - b.x;
float bcy = b.y - c.y;
float d = bcy * (a.x - c.x) + cbx * (a.y - c.y);
float s = bcy * pcx + cbx * pcy;
float t = (c.y - a.y) * pcx + (a.x - c.x) * pcy;
return d < 0 ? s <= 0 && t <= 0 && s + t >= d : s >= 0 && t >= 0 && s + t <= d;
}
public static double lineToPointDiff2d(Vec3 l1, Vec3 l2, Vec3 p) {
return Math.abs((l2.x - l1.x) * (l1.z - p.z) - (l1.x - p.x) * (l2.z - l1.z));
}
}

View file

@ -8,7 +8,6 @@ import com.simibubi.create.AllTags.AllBlockTags;
import com.simibubi.create.api.connectivity.ConnectivityHandler;
import com.simibubi.create.content.contraptions.components.actors.AttachedActorBlock;
import com.simibubi.create.content.contraptions.components.actors.HarvesterBlock;
import com.simibubi.create.content.contraptions.components.actors.PloughBlock;
import com.simibubi.create.content.contraptions.components.actors.PortableStorageInterfaceBlock;
import com.simibubi.create.content.contraptions.components.crank.HandCrankBlock;
import com.simibubi.create.content.contraptions.components.fan.NozzleBlock;
@ -353,10 +352,6 @@ public class BlockMovementChecks {
return state.getValue(BlockStateProperties.FACING) == facing;
if (AllBlocks.MECHANICAL_BEARING.has(state))
return state.getValue(BlockStateProperties.FACING) == facing;
if (AllBlocks.MECHANICAL_HARVESTER.has(state))
return state.getValue(HarvesterBlock.FACING) == facing;
if (AllBlocks.MECHANICAL_PLOUGH.has(state))
return state.getValue(PloughBlock.FACING) == facing;
if (AllBlocks.CART_ASSEMBLER.has(state))
return Direction.DOWN == facing;
@ -364,7 +359,7 @@ public class BlockMovementChecks {
return state.getValue(BlockStateProperties.FACING) == facing;
if (AllBlocks.PORTABLE_STORAGE_INTERFACE.has(state))
return state.getValue(PortableStorageInterfaceBlock.FACING) == facing;
if (state.getBlock() instanceof AttachedActorBlock)
if (state.getBlock() instanceof AttachedActorBlock && !AllBlocks.MECHANICAL_ROLLER.has(state))
return state.getValue(BlockStateProperties.HORIZONTAL_FACING) == facing;
if (AllBlocks.ROPE_PULLEY.has(state))
return facing == Direction.DOWN;

View file

@ -1,7 +1,5 @@
package com.simibubi.create.content.contraptions.components.structureMovement;
import java.util.function.Supplier;
import com.simibubi.create.foundation.networking.SimplePacketBase;
import net.minecraft.core.BlockPos;
@ -38,12 +36,10 @@ public class ContraptionBlockChangedPacket extends SimplePacketBase {
}
@Override
public void handle(Supplier<Context> context) {
context.get()
.enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT,
() -> () -> AbstractContraptionEntity.handleBlockChangedPacket(this)));
context.get()
.setPacketHandled(true);
public boolean handle(Context context) {
context.enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT,
() -> () -> AbstractContraptionEntity.handleBlockChangedPacket(this)));
return true;
}
}

View file

@ -1,7 +1,5 @@
package com.simibubi.create.content.contraptions.components.structureMovement;
import java.util.function.Supplier;
import com.simibubi.create.foundation.networking.SimplePacketBase;
import net.minecraft.network.FriendlyByteBuf;
@ -31,12 +29,10 @@ public class ContraptionDisassemblyPacket extends SimplePacketBase {
}
@Override
public void handle(Supplier<Context> context) {
context.get()
.enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT,
() -> () -> AbstractContraptionEntity.handleDisassemblyPacket(this)));
context.get()
.setPacketHandled(true);
public boolean handle(Context context) {
context.enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT,
() -> () -> AbstractContraptionEntity.handleDisassemblyPacket(this)));
return true;
}
}

View file

@ -1,7 +1,5 @@
package com.simibubi.create.content.contraptions.components.structureMovement;
import java.util.function.Supplier;
import com.simibubi.create.foundation.networking.SimplePacketBase;
import net.minecraft.network.FriendlyByteBuf;
@ -27,12 +25,10 @@ public class ContraptionRelocationPacket extends SimplePacketBase {
}
@Override
public void handle(Supplier<Context> context) {
context.get()
.enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT,
() -> () -> OrientedContraptionEntity.handleRelocationPacket(this)));
context.get()
.setPacketHandled(true);
public boolean handle(Context context) {
context.enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT,
() -> () -> OrientedContraptionEntity.handleRelocationPacket(this)));
return true;
}
}

View file

@ -1,7 +1,5 @@
package com.simibubi.create.content.contraptions.components.structureMovement;
import java.util.function.Supplier;
import com.simibubi.create.foundation.networking.SimplePacketBase;
import net.minecraft.network.FriendlyByteBuf;
@ -41,10 +39,10 @@ public class ContraptionStallPacket extends SimplePacketBase {
}
@Override
public void handle(Supplier<Context> context) {
context.get().enqueueWork(
() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> AbstractContraptionEntity.handleStallPacket(this)));
context.get().setPacketHandled(true);
public boolean handle(Context context) {
context.enqueueWork(
() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> AbstractContraptionEntity.handleStallPacket(this)));
return true;
}
private void writeAll(FriendlyByteBuf buffer, double... doubles) {

View file

@ -1,7 +1,5 @@
package com.simibubi.create.content.contraptions.components.structureMovement;
import java.util.function.Supplier;
import com.simibubi.create.content.logistics.trains.entity.CarriageContraptionEntity;
import com.simibubi.create.foundation.networking.SimplePacketBase;
@ -36,10 +34,9 @@ public class TrainCollisionPacket extends SimplePacketBase {
}
@Override
public void handle(Supplier<Context> context) {
Context ctx = context.get();
ctx.enqueueWork(() -> {
ServerPlayer player = ctx.getSender();
public boolean handle(Context context) {
context.enqueueWork(() -> {
ServerPlayer player = context.getSender();
Level level = player.level;
Entity entity = level.getEntity(contraptionEntityId);
@ -50,7 +47,7 @@ public class TrainCollisionPacket extends SimplePacketBase {
player.level.playSound(player, entity.blockPosition(), SoundEvents.PLAYER_ATTACK_CRIT, SoundSource.NEUTRAL,
1, .75f);
});
ctx.setPacketHandled(true);
return true;
}
}

View file

@ -212,7 +212,8 @@ public class ElevatorContactBlock extends WrenchableDirectionalBlock
@OnlyIn(value = Dist.CLIENT)
protected void displayScreen(ElevatorContactBlockEntity be, Player player) {
if (player instanceof LocalPlayer)
ScreenOpener.open(new ElevatorContactScreen(be.getBlockPos(), be.shortName, be.longName));
ScreenOpener
.open(new ElevatorContactScreen(be.getBlockPos(), be.shortName, be.longName, be.doorControls.mode));
}
public static int getLight(BlockState state) {

View file

@ -2,6 +2,7 @@ package com.simibubi.create.content.contraptions.components.structureMovement.el
import java.util.List;
import com.simibubi.create.content.contraptions.components.actors.DoorControlBehaviour;
import com.simibubi.create.content.contraptions.components.structureMovement.elevator.ElevatorColumn.ColumnCoords;
import com.simibubi.create.content.logistics.block.display.DisplayLinkBlock;
import com.simibubi.create.foundation.blockEntity.BlockEntityBehaviour;
@ -16,6 +17,7 @@ import net.minecraft.world.level.block.state.BlockState;
public class ElevatorContactBlockEntity extends SmartBlockEntity {
public DoorControlBehaviour doorControls;
public ColumnCoords columnCoords;
public boolean activateBlock;
@ -35,7 +37,9 @@ public class ElevatorContactBlockEntity extends SmartBlockEntity {
}
@Override
public void addBehaviours(List<BlockEntityBehaviour> behaviours) {}
public void addBehaviours(List<BlockEntityBehaviour> behaviours) {
behaviours.add(doorControls = new DoorControlBehaviour(this));
}
@Override
protected void write(CompoundTag tag, boolean clientPacket) {

View file

@ -1,40 +1,47 @@
package com.simibubi.create.content.contraptions.components.structureMovement.elevator;
import com.simibubi.create.content.contraptions.components.actors.DoorControl;
import com.simibubi.create.foundation.networking.BlockEntityConfigurationPacket;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.util.Mth;
public class ElevatorContactEditPacket extends BlockEntityConfigurationPacket<ElevatorContactBlockEntity> {
private String shortName;
private String longName;
private DoorControl doorControl;
public ElevatorContactEditPacket(BlockPos pos, String shortName, String longName) {
public ElevatorContactEditPacket(BlockPos pos, String shortName, String longName, DoorControl doorControl) {
super(pos);
this.shortName = shortName;
this.longName = longName;
this.doorControl = doorControl;
}
public ElevatorContactEditPacket(FriendlyByteBuf buffer) {
super(buffer);
}
@Override
protected void writeSettings(FriendlyByteBuf buffer) {
buffer.writeUtf(shortName, 4);
buffer.writeUtf(longName, 30);
buffer.writeVarInt(doorControl.ordinal());
}
@Override
protected void readSettings(FriendlyByteBuf buffer) {
shortName = buffer.readUtf(4);
longName = buffer.readUtf(30);
doorControl = DoorControl.values()[Mth.clamp(buffer.readVarInt(), 0, DoorControl.values().length)];
}
@Override
protected void applySettings(ElevatorContactBlockEntity be) {
be.updateName(shortName, longName);
be.doorControls.set(doorControl);
}
}

View file

@ -5,15 +5,19 @@ import org.lwjgl.glfw.GLFW;
import com.google.common.collect.ImmutableList;
import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.components.actors.DoorControl;
import com.simibubi.create.foundation.gui.AbstractSimiScreen;
import com.simibubi.create.foundation.gui.AllGuiTextures;
import com.simibubi.create.foundation.gui.AllIcons;
import com.simibubi.create.foundation.gui.element.GuiGameElement;
import com.simibubi.create.foundation.gui.widget.IconButton;
import com.simibubi.create.foundation.gui.widget.Label;
import com.simibubi.create.foundation.gui.widget.ScrollInput;
import com.simibubi.create.foundation.gui.widget.TooltipArea;
import com.simibubi.create.foundation.networking.AllPackets;
import com.simibubi.create.foundation.utility.Components;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.Pair;
import net.minecraft.ChatFormatting;
import net.minecraft.client.gui.components.EditBox;
@ -31,12 +35,14 @@ public class ElevatorContactScreen extends AbstractSimiScreen {
private String shortName;
private String longName;
private DoorControl doorControl;
private BlockPos pos;
public ElevatorContactScreen(BlockPos pos, String prevShortName, String prevLongName) {
public ElevatorContactScreen(BlockPos pos, String prevShortName, String prevLongName, DoorControl prevDoorControl) {
super(Lang.translateDirect("elevator_contact.title"));
this.pos = pos;
this.doorControl = prevDoorControl;
background = AllGuiTextures.ELEVATOR_CONTACT;
this.shortName = prevShortName;
this.longName = prevLongName;
@ -88,6 +94,10 @@ public class ElevatorContactScreen extends AbstractSimiScreen {
.component(),
rmbToEdit)));
Pair<ScrollInput, Label> doorControlWidgets =
DoorControl.createWidget(x + 58, y + 57, mode -> doorControl = mode, doorControl);
addRenderableWidget(doorControlWidgets.getFirst());
addRenderableWidget(doorControlWidgets.getSecond());
}
private int centerInput(int x) {
@ -122,6 +132,7 @@ public class ElevatorContactScreen extends AbstractSimiScreen {
.scale(5)
.render(ms);
itemRenderer.renderGuiItem(AllBlocks.TRAIN_DOOR.asStack(), x + 37, y + 58);
}
@Override
@ -164,7 +175,8 @@ public class ElevatorContactScreen extends AbstractSimiScreen {
}
private void confirm() {
AllPackets.getChannel().sendToServer(new ElevatorContactEditPacket(pos, shortName, longName));
AllPackets.getChannel()
.sendToServer(new ElevatorContactEditPacket(pos, shortName, longName, doorControl));
onClose();
}

View file

@ -2,7 +2,6 @@ package com.simibubi.create.content.contraptions.components.structureMovement.el
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
import com.simibubi.create.foundation.networking.AllPackets;
@ -47,21 +46,18 @@ public class ElevatorFloorListPacket extends SimplePacketBase {
}
@Override
public void handle(Supplier<Context> context) {
context.get()
.enqueueWork(() -> {
public boolean handle(Context context) {
context.enqueueWork(() -> {
Entity entityByID = Minecraft.getInstance().level.getEntity(entityId);
if (!(entityByID instanceof AbstractContraptionEntity ace))
return;
if (!(ace.getContraption()instanceof ElevatorContraption ec))
return;
Entity entityByID = Minecraft.getInstance().level.getEntity(entityId);
if (!(entityByID instanceof AbstractContraptionEntity ace))
return;
if (!(ace.getContraption()instanceof ElevatorContraption ec))
return;
ec.namesList = floorsList;
ec.syncControlDisplays();
});
context.get()
.setPacketHandled(true);
ec.namesList = floorsList;
ec.syncControlDisplays();
});
return true;
}
public static class RequestFloorList extends SimplePacketBase {
@ -82,10 +78,9 @@ public class ElevatorFloorListPacket extends SimplePacketBase {
}
@Override
public void handle(Supplier<Context> context) {
Context ctx = context.get();
ctx.enqueueWork(() -> {
ServerPlayer sender = ctx.getSender();
public boolean handle(Context context) {
context.enqueueWork(() -> {
ServerPlayer sender = context.getSender();
Entity entityByID = sender.getLevel()
.getEntity(entityId);
if (!(entityByID instanceof AbstractContraptionEntity ace))
@ -95,7 +90,7 @@ public class ElevatorFloorListPacket extends SimplePacketBase {
AllPackets.getChannel().send(PacketDistributor.PLAYER.with(() -> sender),
new ElevatorFloorListPacket(ace, ec.namesList));
});
ctx.setPacketHandled(true);
return true;
}
}

View file

@ -1,7 +1,5 @@
package com.simibubi.create.content.contraptions.components.structureMovement.elevator;
import java.util.function.Supplier;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
import com.simibubi.create.foundation.networking.SimplePacketBase;
@ -36,10 +34,9 @@ public class ElevatorTargetFloorPacket extends SimplePacketBase {
}
@Override
public void handle(Supplier<Context> context) {
Context ctx = context.get();
ctx.enqueueWork(() -> {
ServerPlayer sender = ctx.getSender();
public boolean handle(Context context) {
context.enqueueWork(() -> {
ServerPlayer sender = context.getSender();
Entity entityByID = sender.getLevel()
.getEntity(entityId);
if (!(entityByID instanceof AbstractContraptionEntity ace))
@ -69,7 +66,7 @@ public class ElevatorTargetFloorPacket extends SimplePacketBase {
elevatorColumn.target(targetY);
elevatorColumn.markDirty();
});
ctx.setPacketHandled(true);
return true;
}
}

View file

@ -1,7 +1,5 @@
package com.simibubi.create.content.contraptions.components.structureMovement.gantry;
import java.util.function.Supplier;
import com.simibubi.create.foundation.networking.SimplePacketBase;
import net.minecraft.network.FriendlyByteBuf;
@ -35,12 +33,10 @@ public class GantryContraptionUpdatePacket extends SimplePacketBase {
}
@Override
public void handle(Supplier<Context> context) {
context.get()
.enqueueWork(
() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> GantryContraptionEntity.handlePacket(this)));
context.get()
.setPacketHandled(true);
public boolean handle(Context context) {
context.enqueueWork(
() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> GantryContraptionEntity.handlePacket(this)));
return true;
}
}

View file

@ -1,7 +1,5 @@
package com.simibubi.create.content.contraptions.components.structureMovement.glue;
import java.util.function.Supplier;
import com.simibubi.create.foundation.networking.SimplePacketBase;
import net.minecraft.client.Minecraft;
@ -9,7 +7,6 @@ import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.network.NetworkEvent.Context;
@ -31,21 +28,22 @@ public class GlueEffectPacket extends SimplePacketBase {
fullBlock = buffer.readBoolean();
}
@Override
public void write(FriendlyByteBuf buffer) {
buffer.writeBlockPos(pos);
buffer.writeByte(direction.get3DDataValue());
buffer.writeBoolean(fullBlock);
}
@OnlyIn(Dist.CLIENT)
public void handle(Supplier<Context> context) {
context.get().enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> {
@Override
public boolean handle(Context context) {
context.enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> {
Minecraft mc = Minecraft.getInstance();
if (!mc.player.blockPosition().closerThan(pos, 100))
return;
SuperGlueItem.spawnParticles(mc.level, pos, direction, fullBlock);
}));
context.get().setPacketHandled(true);
return true;
}
}

View file

@ -1,7 +1,5 @@
package com.simibubi.create.content.contraptions.components.structureMovement.glue;
import java.util.function.Supplier;
import com.simibubi.create.AllSoundEvents;
import com.simibubi.create.foundation.networking.SimplePacketBase;
@ -33,10 +31,9 @@ public class SuperGlueRemovalPacket extends SimplePacketBase {
}
@Override
public void handle(Supplier<Context> context) {
Context ctx = context.get();
ctx.enqueueWork(() -> {
ServerPlayer player = ctx.getSender();
public boolean handle(Context context) {
context.enqueueWork(() -> {
ServerPlayer player = context.getSender();
Entity entity = player.level.getEntity(entityId);
if (!(entity instanceof SuperGlueEntity superGlue))
return;
@ -47,7 +44,7 @@ public class SuperGlueRemovalPacket extends SimplePacketBase {
superGlue.spawnParticles();
entity.discard();
});
ctx.setPacketHandled(true);
return true;
}
}

View file

@ -1,7 +1,6 @@
package com.simibubi.create.content.contraptions.components.structureMovement.glue;
import java.util.Set;
import java.util.function.Supplier;
import com.simibubi.create.foundation.advancement.AllAdvancements;
import com.simibubi.create.foundation.networking.SimplePacketBase;
@ -36,10 +35,9 @@ public class SuperGlueSelectionPacket extends SimplePacketBase {
}
@Override
public void handle(Supplier<Context> context) {
Context ctx = context.get();
ctx.enqueueWork(() -> {
ServerPlayer player = ctx.getSender();
public boolean handle(Context context) {
context.enqueueWork(() -> {
ServerPlayer player = context.getSender();
double range = player.getAttribute(ForgeMod.REACH_DISTANCE.get())
.getValue() + 2;
@ -64,7 +62,7 @@ public class SuperGlueSelectionPacket extends SimplePacketBase {
AllAdvancements.SUPER_GLUE.awardTo(player);
});
ctx.setPacketHandled(true);
return true;
}
}

View file

@ -3,7 +3,6 @@ package com.simibubi.create.content.contraptions.components.structureMovement.in
import java.util.ArrayList;
import java.util.Collection;
import java.util.UUID;
import java.util.function.Supplier;
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
import com.simibubi.create.foundation.networking.SimplePacketBase;
@ -55,10 +54,9 @@ public class ControlsInputPacket extends SimplePacketBase {
}
@Override
public void handle(Supplier<Context> context) {
Context ctx = context.get();
ctx.enqueueWork(() -> {
ServerPlayer player = ctx.getSender();
public boolean handle(Context context) {
context.enqueueWork(() -> {
ServerPlayer player = context.getSender();
Level world = player.getCommandSenderWorld();
UUID uniqueID = player.getUUID();
@ -77,7 +75,7 @@ public class ControlsInputPacket extends SimplePacketBase {
.closerThan(player.position(), 16))
ControlsServerHandler.receivePressed(world, ace, controlsPos, uniqueID, activatedButtons, press);
});
ctx.setPacketHandled(true);
return true;
}
}

View file

@ -1,7 +1,5 @@
package com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls;
import java.util.function.Supplier;
import com.simibubi.create.foundation.networking.SimplePacketBase;
import net.minecraft.network.FriendlyByteBuf;
@ -17,11 +15,9 @@ public class ControlsStopControllingPacket extends SimplePacketBase {
public void write(FriendlyByteBuf buffer) {}
@Override
public void handle(Supplier<Context> context) {
context.get()
.enqueueWork(ControlsHandler::stopControlling);
context.get()
.setPacketHandled(true);
public boolean handle(Context context) {
context.enqueueWork(ControlsHandler::stopControlling);
return true;
}
}

View file

@ -1,7 +1,6 @@
package com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls;
import java.util.UUID;
import java.util.function.Supplier;
import com.simibubi.create.Create;
import com.simibubi.create.content.logistics.trains.entity.Train;
@ -38,10 +37,9 @@ public class HonkPacket extends SimplePacketBase {
}
@Override
public void handle(Supplier<Context> context) {
Context c = context.get();
c.enqueueWork(() -> {
ServerPlayer sender = c.getSender();
public boolean handle(Context context) {
context.enqueueWork(() -> {
ServerPlayer sender = context.getSender();
boolean clientSide = sender == null;
Train train = Create.RAILWAYS.sided(clientSide ? null : sender.level).trains.get(trainId);
if (train == null)
@ -58,7 +56,7 @@ public class HonkPacket extends SimplePacketBase {
}
});
c.setPacketHandled(true);
return true;
}
public static class Serverbound extends HonkPacket {

View file

@ -1,7 +1,6 @@
package com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls;
import java.util.UUID;
import java.util.function.Supplier;
import com.simibubi.create.Create;
import com.simibubi.create.content.logistics.trains.entity.Train;
@ -47,10 +46,9 @@ public class TrainHUDUpdatePacket extends SimplePacketBase {
}
@Override
public void handle(Supplier<Context> context) {
Context c = context.get();
c.enqueueWork(() -> {
ServerPlayer sender = c.getSender();
public boolean handle(Context context) {
context.enqueueWork(() -> {
ServerPlayer sender = context.getSender();
boolean clientSide = sender == null;
Train train = Create.RAILWAYS.sided(clientSide ? null : sender.level).trains.get(trainId);
if (train == null)
@ -62,9 +60,8 @@ public class TrainHUDUpdatePacket extends SimplePacketBase {
train.speed = speed;
train.fuelTicks = fuelTicks;
}
});
c.setPacketHandled(true);
return true;
}
public static class Serverbound extends TrainHUDUpdatePacket {

View file

@ -1,7 +1,5 @@
package com.simibubi.create.content.contraptions.components.structureMovement.sync;
import java.util.function.Supplier;
import com.simibubi.create.foundation.networking.AllPackets;
import com.simibubi.create.foundation.networking.SimplePacketBase;
@ -40,26 +38,23 @@ public class ClientMotionPacket extends SimplePacketBase {
}
@Override
public void handle(Supplier<Context> context) {
context.get()
.enqueueWork(() -> {
ServerPlayer sender = context.get()
.getSender();
if (sender == null)
return;
sender.setDeltaMovement(motion);
sender.setOnGround(onGround);
if (onGround) {
sender.causeFallDamage(sender.fallDistance, 1, DamageSource.FALL);
sender.fallDistance = 0;
sender.connection.aboveGroundTickCount = 0;
sender.connection.aboveGroundVehicleTickCount = 0;
}
AllPackets.getChannel().send(PacketDistributor.TRACKING_ENTITY.with(() -> sender),
new LimbSwingUpdatePacket(sender.getId(), sender.position(), limbSwing));
});
context.get()
.setPacketHandled(true);
public boolean handle(Context context) {
context.enqueueWork(() -> {
ServerPlayer sender = context.getSender();
if (sender == null)
return;
sender.setDeltaMovement(motion);
sender.setOnGround(onGround);
if (onGround) {
sender.causeFallDamage(sender.fallDistance, 1, DamageSource.FALL);
sender.fallDistance = 0;
sender.connection.aboveGroundTickCount = 0;
sender.connection.aboveGroundVehicleTickCount = 0;
}
AllPackets.getChannel().send(PacketDistributor.TRACKING_ENTITY.with(() -> sender),
new LimbSwingUpdatePacket(sender.getId(), sender.position(), limbSwing));
});
return true;
}
}

View file

@ -1,7 +1,5 @@
package com.simibubi.create.content.contraptions.components.structureMovement.sync;
import java.util.function.Supplier;
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
import com.simibubi.create.foundation.networking.SimplePacketBase;
@ -38,16 +36,14 @@ public class ContraptionFluidPacket extends SimplePacketBase {
}
@Override
public void handle(Supplier<Context> context) {
context.get()
.enqueueWork(() -> {
Entity entityByID = Minecraft.getInstance().level.getEntity(entityId);
if (!(entityByID instanceof AbstractContraptionEntity))
return;
AbstractContraptionEntity contraptionEntity = (AbstractContraptionEntity) entityByID;
contraptionEntity.getContraption().handleContraptionFluidPacket(localPos, containedFluid);
});
context.get()
.setPacketHandled(true);
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;
}
}

View file

@ -1,7 +1,5 @@
package com.simibubi.create.content.contraptions.components.structureMovement.sync;
import java.util.function.Supplier;
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
import com.simibubi.create.foundation.networking.SimplePacketBase;
@ -46,9 +44,9 @@ public class ContraptionInteractionPacket extends SimplePacketBase {
}
@Override
public void handle(Supplier<Context> context) {
context.get().enqueueWork(() -> {
ServerPlayer sender = context.get().getSender();
public boolean handle(Context context) {
context.enqueueWork(() -> {
ServerPlayer sender = context.getSender();
if (sender == null)
return;
Entity entityByID = sender.getLevel().getEntity(target);
@ -66,7 +64,7 @@ public class ContraptionInteractionPacket extends SimplePacketBase {
if (contraptionEntity.handlePlayerInteraction(sender, localPos, face, interactionHand))
sender.swing(interactionHand, true);
});
context.get().setPacketHandled(true);
return true;
}
}

View file

@ -3,7 +3,6 @@ package com.simibubi.create.content.contraptions.components.structureMovement.sy
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.function.Supplier;
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
import com.simibubi.create.foundation.networking.SimplePacketBase;
@ -52,29 +51,27 @@ public class ContraptionSeatMappingPacket extends SimplePacketBase {
}
@Override
public void handle(Supplier<Context> context) {
context.get()
.enqueueWork(() -> {
Entity entityByID = Minecraft.getInstance().level.getEntity(entityID);
if (!(entityByID instanceof AbstractContraptionEntity))
public boolean handle(Context context) {
context.enqueueWork(() -> {
Entity entityByID = Minecraft.getInstance().level.getEntity(entityID);
if (!(entityByID instanceof AbstractContraptionEntity))
return;
AbstractContraptionEntity contraptionEntity = (AbstractContraptionEntity) entityByID;
if (dismountedID != -1) {
Entity dismountedByID = Minecraft.getInstance().level.getEntity(dismountedID);
if (Minecraft.getInstance().player != dismountedByID)
return;
AbstractContraptionEntity contraptionEntity = (AbstractContraptionEntity) entityByID;
if (dismountedID != -1) {
Entity dismountedByID = Minecraft.getInstance().level.getEntity(dismountedID);
if (Minecraft.getInstance().player != dismountedByID)
return;
Vec3 transformedVector = contraptionEntity.getPassengerPosition(dismountedByID, 1);
if (transformedVector != null)
dismountedByID.getPersistentData()
.put("ContraptionDismountLocation", VecHelper.writeNBT(transformedVector));
}
contraptionEntity.getContraption()
.setSeatMapping(mapping);
});
context.get()
.setPacketHandled(true);
Vec3 transformedVector = contraptionEntity.getPassengerPosition(dismountedByID, 1);
if (transformedVector != null)
dismountedByID.getPersistentData()
.put("ContraptionDismountLocation", VecHelper.writeNBT(transformedVector));
}
contraptionEntity.getContraption()
.setSeatMapping(mapping);
});
return true;
}
}

View file

@ -1,7 +1,5 @@
package com.simibubi.create.content.contraptions.components.structureMovement.sync;
import java.util.function.Supplier;
import com.simibubi.create.foundation.networking.SimplePacketBase;
import net.minecraft.client.Minecraft;
@ -40,23 +38,21 @@ public class LimbSwingUpdatePacket extends SimplePacketBase {
}
@Override
public void handle(Supplier<Context> context) {
context.get()
.enqueueWork(() -> {
ClientLevel world = Minecraft.getInstance().level;
if (world == null)
return;
Entity entity = world.getEntity(entityId);
if (entity == null)
return;
CompoundTag data = entity.getPersistentData();
data.putInt("LastOverrideLimbSwingUpdate", 0);
data.putFloat("OverrideLimbSwing", limbSwing);
entity.lerpTo(position.x, position.y, position.z, entity.getYRot(),
entity.getXRot(), 2, false);
});
context.get()
.setPacketHandled(true);
public boolean handle(Context context) {
context.enqueueWork(() -> {
ClientLevel world = Minecraft.getInstance().level;
if (world == null)
return;
Entity entity = world.getEntity(entityId);
if (entity == null)
return;
CompoundTag data = entity.getPersistentData();
data.putInt("LastOverrideLimbSwingUpdate", 0);
data.putFloat("OverrideLimbSwing", limbSwing);
entity.lerpTo(position.x, position.y, position.z, entity.getYRot(),
entity.getXRot(), 2, false);
});
return true;
}
}

View file

@ -1,7 +1,5 @@
package com.simibubi.create.content.contraptions.components.structureMovement.train;
import java.util.function.Supplier;
import com.simibubi.create.foundation.networking.SimplePacketBase;
import net.minecraft.network.FriendlyByteBuf;
@ -30,16 +28,13 @@ public class CouplingCreationPacket extends SimplePacketBase {
}
@Override
public void handle(Supplier<Context> context) {
context.get()
.enqueueWork(() -> {
ServerPlayer sender = context.get()
.getSender();
if (sender != null)
CouplingHandler.tryToCoupleCarts(sender, sender.level, id1, id2);
});
context.get()
.setPacketHandled(true);
public boolean handle(Context context) {
context.enqueueWork(() -> {
ServerPlayer sender = context.getSender();
if (sender != null)
CouplingHandler.tryToCoupleCarts(sender, sender.level, id1, id2);
});
return true;
}
}
}

View file

@ -1,7 +1,5 @@
package com.simibubi.create.content.contraptions.components.structureMovement.train.capability;
import java.util.function.Supplier;
import com.simibubi.create.foundation.networking.SimplePacketBase;
import net.minecraft.client.Minecraft;
@ -37,11 +35,9 @@ public class MinecartControllerUpdatePacket extends SimplePacketBase {
}
@Override
public void handle(Supplier<Context> context) {
context.get()
.enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> this::handleCL));
context.get()
.setPacketHandled(true);
public boolean handle(Context context) {
context.enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> this::handleCL));
return true;
}
@OnlyIn(Dist.CLIENT)

View file

@ -1,7 +1,5 @@
package com.simibubi.create.content.contraptions.fluids.actors;
import java.util.function.Supplier;
import com.simibubi.create.content.contraptions.fluids.FluidFX;
import com.simibubi.create.foundation.networking.SimplePacketBase;
@ -29,21 +27,21 @@ public class FluidSplashPacket extends SimplePacketBase {
fluid = buffer.readFluidStack();
}
@Override
public void write(FriendlyByteBuf buffer) {
buffer.writeBlockPos(pos);
buffer.writeFluidStack(fluid);
}
public void handle(Supplier<Context> ctx) {
ctx.get()
.enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> {
if (Minecraft.getInstance().player.position()
.distanceTo(new Vec3(pos.getX(), pos.getY(), pos.getZ())) > 100)
return;
FluidFX.splash(pos, fluid);
}));
ctx.get()
.setPacketHandled(true);
@Override
public boolean handle(Context context) {
context.enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> {
if (Minecraft.getInstance().player.position()
.distanceTo(new Vec3(pos.getX(), pos.getY(), pos.getZ())) > 100)
return;
FluidFX.splash(pos, fluid);
}));
return true;
}
}

View file

@ -39,10 +39,11 @@ public class SmartFluidPipeBlockEntity extends SmartBlockEntity {
registerAwardables(behaviours, FluidPropagator.getSharedTriggers());
}
private void onFilterChanged(ItemStack newFilter) {
private boolean onFilterChanged(ItemStack newFilter) {
if (level.isClientSide)
return;
return true;
FluidPropagator.propagateChangedPipe(level, worldPosition, getBlockState());
return true;
}
class SmartPipeBehaviour extends StraightPipeFluidTransportBehaviour {

View file

@ -1,7 +1,5 @@
package com.simibubi.create.content.curiosities.armor;
import java.util.function.Supplier;
import com.simibubi.create.AllItems;
import com.simibubi.create.foundation.networking.AllPackets;
import com.simibubi.create.foundation.networking.SimplePacketBase;
@ -137,14 +135,14 @@ public final class NetheriteDivingHandler {
}
@Override
public void handle(Supplier<Context> context) {
context.get().enqueueWork(() -> {
public boolean handle(Context context) {
context.enqueueWork(() -> {
Entity entity = Minecraft.getInstance().level.getEntity(entityId);
if (entity != null) {
entity.getPersistentData().putBoolean(FIRE_IMMUNE_KEY, fireImmune);
}
});
context.get().setPacketHandled(true);
return true;
}
}
}

View file

@ -1,13 +1,11 @@
package com.simibubi.create.content.curiosities.bell;
import java.util.function.Supplier;
import com.simibubi.create.CreateClient;
import com.simibubi.create.foundation.networking.SimplePacketBase;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraftforge.network.NetworkEvent;
import net.minecraftforge.network.NetworkEvent.Context;
public class SoulPulseEffectPacket extends SimplePacketBase {
@ -35,11 +33,11 @@ public class SoulPulseEffectPacket extends SimplePacketBase {
}
@Override
public void handle(Supplier<NetworkEvent.Context> context) {
context.get().enqueueWork(() -> {
public boolean handle(Context context) {
context.enqueueWork(() -> {
CreateClient.SOUL_PULSE_EFFECT_HANDLER.addPulse(new SoulPulseEffect(pos, distance, canOverlap));
});
context.get().setPacketHandled(true);
return true;
}
}

View file

@ -1,23 +1,37 @@
package com.simibubi.create.content.curiosities.deco;
import java.lang.ref.WeakReference;
import java.util.Map;
import com.simibubi.create.content.contraptions.components.actors.DoorControl;
import com.simibubi.create.content.contraptions.components.actors.DoorControlBehaviour;
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour;
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
import com.simibubi.create.content.contraptions.components.structureMovement.elevator.ElevatorColumn;
import com.simibubi.create.content.contraptions.components.structureMovement.elevator.ElevatorColumn.ColumnCoords;
import com.simibubi.create.content.contraptions.components.structureMovement.elevator.ElevatorContraption;
import com.simibubi.create.content.logistics.trains.entity.Carriage;
import com.simibubi.create.content.logistics.trains.entity.CarriageContraptionEntity;
import com.simibubi.create.content.logistics.trains.entity.CarriageSyncData;
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.GlobalStation;
import com.simibubi.create.foundation.blockEntity.BlockEntityBehaviour;
import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Direction.AxisDirection;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.DoorBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.DoubleBlockHalf;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo;
import net.minecraft.world.phys.Vec3;
public class SlidingDoorMovementBehaviour implements MovementBehaviour {
@ -25,12 +39,12 @@ public class SlidingDoorMovementBehaviour implements MovementBehaviour {
public boolean renderAsNormalBlockEntity() {
return true;
}
@Override
public boolean mustTickWhileDisabled() {
return true;
}
@Override
public void tick(MovementContext context) {
StructureBlockInfo structureBlockInfo = context.contraption.getBlocks()
@ -43,7 +57,7 @@ public class SlidingDoorMovementBehaviour implements MovementBehaviour {
tickOpen(context, open);
Map<BlockPos, BlockEntity> tes = context.contraption.presentBlockEntities;
if (!(tes.get(context.localPos) instanceof SlidingDoorBlockEntity doorTE))
if (!(tes.get(context.localPos)instanceof SlidingDoorBlockEntity doorTE))
return;
boolean wasSettled = doorTE.animation.settled();
doorTE.animation.chase(open ? 1 : 0, .15f, Chaser.LINEAR);
@ -105,14 +119,90 @@ public class SlidingDoorMovementBehaviour implements MovementBehaviour {
protected boolean shouldOpen(MovementContext context) {
if (context.disabled)
return false;
if (context.contraption instanceof ElevatorContraption ec && ec.arrived)
return true;
if (context.contraption.entity instanceof CarriageContraptionEntity cce) {
CarriageSyncData carriageData = cce.getCarriageData();
if (Math.abs(carriageData.distanceToDestination) > 1)
return false;
Contraption contraption = context.contraption;
boolean canOpen = context.motion.length() < 1 / 128f && !contraption.entity.isStalled()
|| contraption instanceof ElevatorContraption ec && ec.arrived;
if (!canOpen) {
context.temporaryData = null;
return false;
}
return context.motion.length() < 1 / 128f && !context.contraption.entity.isStalled();
if (context.temporaryData instanceof WeakReference<?> wr && wr.get()instanceof DoorControlBehaviour dcb)
if (dcb.blockEntity != null && !dcb.blockEntity.isRemoved())
return shouldOpenAt(dcb, context);
context.temporaryData = null;
DoorControlBehaviour doorControls = null;
if (contraption instanceof ElevatorContraption ec)
doorControls = getElevatorDoorControl(ec, context);
if (context.contraption.entity instanceof CarriageContraptionEntity cce)
doorControls = getTrainStationDoorControl(cce, context);
if (doorControls == null)
return false;
context.temporaryData = new WeakReference<>(doorControls);
return shouldOpenAt(doorControls, context);
}
protected boolean shouldOpenAt(DoorControlBehaviour controller, MovementContext context) {
if (controller.mode == DoorControl.ALL)
return true;
if (controller.mode == DoorControl.NONE)
return false;
return controller.mode.matches(getDoorFacing(context));
}
protected DoorControlBehaviour getElevatorDoorControl(ElevatorContraption ec, MovementContext context) {
Integer currentTargetY = ec.getCurrentTargetY(context.world);
if (currentTargetY == null)
return null;
ColumnCoords columnCoords = ec.getGlobalColumn();
if (columnCoords == null)
return null;
ElevatorColumn elevatorColumn = ElevatorColumn.get(context.world, columnCoords);
if (elevatorColumn == null)
return null;
return BlockEntityBehaviour.get(context.world, elevatorColumn.contactAt(currentTargetY),
DoorControlBehaviour.TYPE);
}
protected DoorControlBehaviour getTrainStationDoorControl(CarriageContraptionEntity cce, MovementContext context) {
Carriage carriage = cce.getCarriage();
if (carriage == null || carriage.train == null)
return null;
GlobalStation currentStation = carriage.train.getCurrentStation();
if (currentStation == null)
return null;
BlockPos stationPos = currentStation.getBlockEntityPos();
ResourceKey<Level> stationDim = currentStation.getBlockEntityDimension();
MinecraftServer server = context.world.getServer();
if (server == null)
return null;
ServerLevel stationLevel = server.getLevel(stationDim);
if (stationLevel == null || !stationLevel.isLoaded(stationPos))
return null;
return BlockEntityBehaviour.get(stationLevel, stationPos, DoorControlBehaviour.TYPE);
}
protected Direction getDoorFacing(MovementContext context) {
Direction stateFacing = context.state.getValue(DoorBlock.FACING);
Direction originalFacing = Direction.get(AxisDirection.POSITIVE, stateFacing.getAxis());
Vec3 centerOfContraption = context.contraption.bounds.getCenter();
Vec3 diff = Vec3.atCenterOf(context.localPos)
.add(Vec3.atLowerCornerOf(stateFacing.getNormal())
.scale(-.45f))
.subtract(centerOfContraption);
if (originalFacing.getAxis()
.choose(diff.x, diff.y, diff.z) < 0)
originalFacing = originalFacing.getOpposite();
Vec3 directionVec = Vec3.atLowerCornerOf(originalFacing.getNormal());
directionVec = context.rotation.apply(directionVec);
return Direction.getNearest(directionVec.x, directionVec.y, directionVec.z);
}
}

View file

@ -1,7 +1,5 @@
package com.simibubi.create.content.curiosities.symmetry;
import java.util.function.Supplier;
import com.simibubi.create.content.curiosities.symmetry.mirror.SymmetryMirror;
import com.simibubi.create.foundation.networking.SimplePacketBase;
@ -33,9 +31,9 @@ public class ConfigureSymmetryWandPacket extends SimplePacketBase {
}
@Override
public void handle(Supplier<Context> context) {
context.get().enqueueWork(() -> {
ServerPlayer player = context.get().getSender();
public boolean handle(Context context) {
context.enqueueWork(() -> {
ServerPlayer player = context.getSender();
if (player == null) {
return;
}
@ -44,7 +42,7 @@ public class ConfigureSymmetryWandPacket extends SimplePacketBase {
SymmetryWandItem.configureSettings(stack, mirror);
}
});
context.get().setPacketHandled(true);
return true;
}
}

View file

@ -2,7 +2,6 @@ package com.simibubi.create.content.curiosities.symmetry;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;
import com.simibubi.create.foundation.networking.SimplePacketBase;
@ -43,14 +42,14 @@ public class SymmetryEffectPacket extends SimplePacketBase {
}
@Override
public void handle(Supplier<Context> ctx) {
ctx.get().enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> {
public boolean handle(Context context) {
context.enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> {
if (Minecraft.getInstance().player.position().distanceTo(Vec3.atLowerCornerOf(mirror)) > 100)
return;
for (BlockPos to : positions)
SymmetryHandler.drawEffect(mirror, to);
}));
ctx.get().setPacketHandled(true);
return true;
}
}

View file

@ -1,7 +1,5 @@
package com.simibubi.create.content.curiosities.toolbox;
import java.util.function.Supplier;
import org.apache.commons.lang3.mutable.MutableBoolean;
import com.simibubi.create.foundation.networking.SimplePacketBase;
@ -35,10 +33,9 @@ public class ToolboxDisposeAllPacket extends SimplePacketBase {
}
@Override
public void handle(Supplier<Context> context) {
Context ctx = context.get();
ctx.enqueueWork(() -> {
ServerPlayer player = ctx.getSender();
public boolean handle(Context context) {
context.enqueueWork(() -> {
ServerPlayer player = context.getSender();
Level world = player.level;
BlockEntity blockEntity = world.getBlockEntity(toolboxPos);
@ -73,9 +70,8 @@ public class ToolboxDisposeAllPacket extends SimplePacketBase {
if (sendData.booleanValue())
ToolboxHandler.syncData(player);
});
ctx.setPacketHandled(true);
return true;
}
}

View file

@ -1,7 +1,5 @@
package com.simibubi.create.content.curiosities.toolbox;
import java.util.function.Supplier;
import com.simibubi.create.foundation.networking.SimplePacketBase;
import net.minecraft.core.BlockPos;
@ -44,10 +42,9 @@ public class ToolboxEquipPacket extends SimplePacketBase {
}
@Override
public void handle(Supplier<Context> context) {
Context ctx = context.get();
ctx.enqueueWork(() -> {
ServerPlayer player = ctx.getSender();
public boolean handle(Context context) {
context.enqueueWork(() -> {
ServerPlayer player = context.getSender();
Level world = player.level;
if (toolboxPos == null) {
@ -102,7 +99,7 @@ public class ToolboxEquipPacket extends SimplePacketBase {
toolboxBlockEntity.connectPlayer(slot, player, hotbarSlot);
ToolboxHandler.syncData(player);
});
ctx.setPacketHandled(true);
return true;
}
}

View file

@ -1,7 +1,5 @@
package com.simibubi.create.content.curiosities.tools;
import java.util.function.Supplier;
import com.simibubi.create.foundation.networking.SimplePacketBase;
import net.minecraft.network.FriendlyByteBuf;
@ -27,23 +25,20 @@ public class BlueprintAssignCompleteRecipePacket extends SimplePacketBase {
}
@Override
public void handle(Supplier<Context> context) {
context.get()
.enqueueWork(() -> {
ServerPlayer player = context.get()
.getSender();
if (player == null)
return;
if (player.containerMenu instanceof BlueprintMenu) {
BlueprintMenu c = (BlueprintMenu) player.containerMenu;
player.getLevel()
.getRecipeManager()
.byKey(recipeID)
.ifPresent(r -> BlueprintItem.assignCompleteRecipe(c.ghostInventory, r));
}
});
context.get()
.setPacketHandled(true);
public boolean handle(Context context) {
context.enqueueWork(() -> {
ServerPlayer player = context.getSender();
if (player == null)
return;
if (player.containerMenu instanceof BlueprintMenu) {
BlueprintMenu c = (BlueprintMenu) player.containerMenu;
player.getLevel()
.getRecipeManager()
.byKey(recipeID)
.ifPresent(r -> BlueprintItem.assignCompleteRecipe(c.ghostInventory, r));
}
});
return true;
}
}

View file

@ -1,7 +1,5 @@
package com.simibubi.create.content.curiosities.tools;
import java.util.function.Supplier;
import com.simibubi.create.foundation.networking.SimplePacketBase;
import net.minecraft.network.FriendlyByteBuf;
@ -53,33 +51,30 @@ public class ExtendoGripInteractionPacket extends SimplePacketBase {
}
@Override
public void handle(Supplier<Context> context) {
context.get()
.enqueueWork(() -> {
ServerPlayer sender = context.get()
.getSender();
if (sender == null)
public boolean handle(Context context) {
context.enqueueWork(() -> {
ServerPlayer sender = context.getSender();
if (sender == null)
return;
Entity entityByID = sender.getLevel()
.getEntity(target);
if (entityByID != null && ExtendoGripItem.isHoldingExtendoGrip(sender)) {
double d = sender.getAttribute(ForgeMod.REACH_DISTANCE.get())
.getValue();
if (!sender.hasLineOfSight(entityByID))
d -= 3;
d *= d;
if (sender.distanceToSqr(entityByID) > d)
return;
Entity entityByID = sender.getLevel()
.getEntity(target);
if (entityByID != null && ExtendoGripItem.isHoldingExtendoGrip(sender)) {
double d = sender.getAttribute(ForgeMod.REACH_DISTANCE.get())
.getValue();
if (!sender.hasLineOfSight(entityByID))
d -= 3;
d *= d;
if (sender.distanceToSqr(entityByID) > d)
return;
if (interactionHand == null)
sender.attack(entityByID);
else if (specificPoint == null)
sender.interactOn(entityByID, interactionHand);
else
entityByID.interactAt(sender, specificPoint, interactionHand);
}
});
context.get()
.setPacketHandled(true);
if (interactionHand == null)
sender.attack(entityByID);
else if (specificPoint == null)
sender.interactOn(entityByID, interactionHand);
else
entityByID.interactAt(sender, specificPoint, interactionHand);
}
});
return true;
}
}

View file

@ -148,11 +148,11 @@ public class PotatoProjectileTypeManager {
}
@Override
public void handle(Supplier<Context> context) {
context.get().enqueueWork(() -> {
public boolean handle(Context context) {
context.enqueueWork(() -> {
fromBuffer(buffer);
});
context.get().setPacketHandled(true);
return true;
}
}

View file

@ -1,7 +1,5 @@
package com.simibubi.create.content.curiosities.zapper;
import java.util.function.Supplier;
import com.simibubi.create.foundation.networking.SimplePacketBase;
import net.minecraft.network.FriendlyByteBuf;
@ -32,9 +30,9 @@ public abstract class ConfigureZapperPacket extends SimplePacketBase {
}
@Override
public void handle(Supplier<Context> context) {
context.get().enqueueWork(() -> {
ServerPlayer player = context.get().getSender();
public boolean handle(Context context) {
context.enqueueWork(() -> {
ServerPlayer player = context.getSender();
if (player == null) {
return;
}
@ -43,7 +41,7 @@ public abstract class ConfigureZapperPacket extends SimplePacketBase {
configureZapper(stack);
}
});
context.get().setPacketHandled(true);
return true;
}
public abstract void configureZapper(ItemStack stack);

View file

@ -1,7 +1,5 @@
package com.simibubi.create.content.curiosities.zapper;
import java.util.function.Supplier;
import com.simibubi.create.foundation.networking.SimplePacketBase;
import net.minecraft.client.Minecraft;
@ -53,26 +51,24 @@ public abstract class ShootGadgetPacket extends SimplePacketBase {
@Override
@OnlyIn(Dist.CLIENT)
public final void handle(Supplier<Context> context) {
context.get()
.enqueueWork(() -> {
Entity renderViewEntity = Minecraft.getInstance()
.getCameraEntity();
if (renderViewEntity == null)
return;
if (renderViewEntity.position()
.distanceTo(location) > 100)
return;
public boolean handle(Context context) {
context.enqueueWork(() -> {
Entity renderViewEntity = Minecraft.getInstance()
.getCameraEntity();
if (renderViewEntity == null)
return;
if (renderViewEntity.position()
.distanceTo(location) > 100)
return;
ShootableGadgetRenderHandler handler = getHandler();
handleAdditional();
if (self)
handler.shoot(hand, location);
else
handler.playSound(hand, location);
});
context.get()
.setPacketHandled(true);
ShootableGadgetRenderHandler handler = getHandler();
handleAdditional();
if (self)
handler.shoot(hand, location);
else
handler.playSound(hand, location);
});
return true;
}
}

View file

@ -1,7 +1,5 @@
package com.simibubi.create.content.logistics.block.depot;
import java.util.function.Supplier;
import com.simibubi.create.foundation.networking.SimplePacketBase;
import net.minecraft.core.BlockPos;
@ -29,23 +27,19 @@ public class EjectorElytraPacket extends SimplePacketBase {
}
@Override
public void handle(Supplier<Context> context) {
context.get()
.enqueueWork(() -> {
ServerPlayer player = context.get()
.getSender();
if (player == null)
return;
Level world = player.level;
if (world == null || !world.isLoaded(pos))
return;
BlockEntity blockEntity = world.getBlockEntity(pos);
if (blockEntity instanceof EjectorBlockEntity)
((EjectorBlockEntity) blockEntity).deployElytra(player);
});
context.get()
.setPacketHandled(true);
public boolean handle(Context context) {
context.enqueueWork(() -> {
ServerPlayer player = context.getSender();
if (player == null)
return;
Level world = player.level;
if (world == null || !world.isLoaded(pos))
return;
BlockEntity blockEntity = world.getBlockEntity(pos);
if (blockEntity instanceof EjectorBlockEntity)
((EjectorBlockEntity) blockEntity).deployElytra(player);
});
return true;
}
}

View file

@ -1,7 +1,5 @@
package com.simibubi.create.content.logistics.block.depot;
import java.util.function.Supplier;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.networking.SimplePacketBase;
@ -43,26 +41,22 @@ public class EjectorPlacementPacket extends SimplePacketBase {
}
@Override
public void handle(Supplier<Context> context) {
context.get()
.enqueueWork(() -> {
ServerPlayer player = context.get()
.getSender();
if (player == null)
return;
Level world = player.level;
if (world == null || !world.isLoaded(pos))
return;
BlockEntity blockEntity = world.getBlockEntity(pos);
BlockState state = world.getBlockState(pos);
if (blockEntity instanceof EjectorBlockEntity)
((EjectorBlockEntity) blockEntity).setTarget(h, v);
if (AllBlocks.WEIGHTED_EJECTOR.has(state))
world.setBlockAndUpdate(pos, state.setValue(EjectorBlock.HORIZONTAL_FACING, facing));
});
context.get()
.setPacketHandled(true);
public boolean handle(Context context) {
context.enqueueWork(() -> {
ServerPlayer player = context.getSender();
if (player == null)
return;
Level world = player.level;
if (world == null || !world.isLoaded(pos))
return;
BlockEntity blockEntity = world.getBlockEntity(pos);
BlockState state = world.getBlockState(pos);
if (blockEntity instanceof EjectorBlockEntity)
((EjectorBlockEntity) blockEntity).setTarget(h, v);
if (AllBlocks.WEIGHTED_EJECTOR.has(state))
world.setBlockAndUpdate(pos, state.setValue(EjectorBlock.HORIZONTAL_FACING, facing));
});
return true;
}
}

View file

@ -1,7 +1,6 @@
package com.simibubi.create.content.logistics.block.mechanicalArm;
import java.util.Collection;
import java.util.function.Supplier;
import com.simibubi.create.foundation.networking.SimplePacketBase;
@ -45,26 +44,22 @@ public class ArmPlacementPacket extends SimplePacketBase {
}
@Override
public void handle(Supplier<Context> context) {
context.get()
.enqueueWork(() -> {
ServerPlayer player = context.get()
.getSender();
if (player == null)
return;
Level world = player.level;
if (world == null || !world.isLoaded(pos))
return;
BlockEntity blockEntity = world.getBlockEntity(pos);
if (!(blockEntity instanceof ArmBlockEntity))
return;
ArmBlockEntity arm = (ArmBlockEntity) blockEntity;
arm.interactionPointTag = receivedTag;
});
context.get()
.setPacketHandled(true);
public boolean handle(Context context) {
context.enqueueWork(() -> {
ServerPlayer player = context.getSender();
if (player == null)
return;
Level world = player.level;
if (world == null || !world.isLoaded(pos))
return;
BlockEntity blockEntity = world.getBlockEntity(pos);
if (!(blockEntity instanceof ArmBlockEntity))
return;
ArmBlockEntity arm = (ArmBlockEntity) blockEntity;
arm.interactionPointTag = receivedTag;
});
return true;
}
}

View file

@ -193,8 +193,10 @@ public class StockpileSwitchBlockEntity extends SmartBlockEntity {
@Override
public void addBehaviours(List<BlockEntityBehaviour> behaviours) {
filtering =
new FilteringBehaviour(this, new FilteredDetectorFilterSlot()).withCallback($ -> updateCurrentLevel());
filtering = new FilteringBehaviour(this, new FilteredDetectorFilterSlot()).withCallback($ -> {
updateCurrentLevel();
return true;
});
behaviours.add(filtering);
InterfaceProvider towardBlockFacing = InterfaceProvider.towardBlockFacing();

View file

@ -1,7 +1,5 @@
package com.simibubi.create.content.logistics.item;
import java.util.function.Supplier;
import com.simibubi.create.AllItems;
import com.simibubi.create.foundation.networking.SimplePacketBase;
@ -41,9 +39,9 @@ public abstract class LinkedControllerPacketBase extends SimplePacketBase {
}
@Override
public void handle(Supplier<Context> context) {
context.get().enqueueWork(() -> {
ServerPlayer player = context.get().getSender();
public boolean handle(Context context) {
context.enqueueWork(() -> {
ServerPlayer player = context.getSender();
if (player == null)
return;
@ -62,8 +60,7 @@ public abstract class LinkedControllerPacketBase extends SimplePacketBase {
handleItem(player, controller);
}
});
context.get().setPacketHandled(true);
return true;
}
protected abstract void handleItem(ServerPlayer player, ItemStack heldItem);

View file

@ -1,7 +1,5 @@
package com.simibubi.create.content.logistics.item.filter;
import java.util.function.Supplier;
import com.simibubi.create.content.logistics.item.filter.AttributeFilterMenu.WhitelistMode;
import com.simibubi.create.foundation.networking.SimplePacketBase;
@ -40,9 +38,9 @@ public class FilterScreenPacket extends SimplePacketBase {
}
@Override
public void handle(Supplier<Context> context) {
context.get().enqueueWork(() -> {
ServerPlayer player = context.get().getSender();
public boolean handle(Context context) {
context.enqueueWork(() -> {
ServerPlayer player = context.getSender();
if (player == null)
return;
@ -77,7 +75,7 @@ public class FilterScreenPacket extends SimplePacketBase {
}
});
context.get().setPacketHandled(true);
return true;
}
}

View file

@ -6,9 +6,11 @@ import com.jozufozu.flywheel.util.transform.TransformStack;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.PoseStack.Pose;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.logistics.trains.track.TrackBlockEntityTilt;
import com.simibubi.create.content.logistics.trains.track.TrackRenderer;
import com.simibubi.create.foundation.utility.Couple;
import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.NBTHelper;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.core.BlockPos;
@ -37,6 +39,7 @@ public class BezierConnection implements Iterable<BezierConnection.Segment> {
public Couple<Vec3> starts;
public Couple<Vec3> axes;
public Couple<Vec3> normals;
public Couple<Integer> smoothing;
public boolean primary;
public boolean hasGirder;
@ -66,8 +69,15 @@ public class BezierConnection implements Iterable<BezierConnection.Segment> {
}
public BezierConnection secondary() {
return new BezierConnection(tePositions.swap(), starts.swap(), axes.swap(), normals.swap(), !primary,
hasGirder);
BezierConnection bezierConnection =
new BezierConnection(tePositions.swap(), starts.swap(), axes.swap(), normals.swap(), !primary, hasGirder);
if (smoothing != null)
bezierConnection.smoothing = smoothing.swap();
return bezierConnection;
}
public BezierConnection clone() {
return secondary().secondary();
}
public BezierConnection(CompoundTag compound, BlockPos localTo) {
@ -78,6 +88,10 @@ public class BezierConnection implements Iterable<BezierConnection.Segment> {
Couple.deserializeEach(compound.getList("Axes", Tag.TAG_COMPOUND), VecHelper::readNBTCompound),
Couple.deserializeEach(compound.getList("Normals", Tag.TAG_COMPOUND), VecHelper::readNBTCompound),
compound.getBoolean("Primary"), compound.getBoolean("Girder"));
if (compound.contains("Smoothing"))
smoothing =
Couple.deserializeEach(compound.getList("Smoothing", Tag.TAG_COMPOUND), NBTHelper::intFromCompound);
}
public CompoundTag write(BlockPos localTo) {
@ -91,6 +105,10 @@ public class BezierConnection implements Iterable<BezierConnection.Segment> {
compound.put("Starts", starts.serializeEach(VecHelper::writeNBTCompound));
compound.put("Axes", axes.serializeEach(VecHelper::writeNBTCompound));
compound.put("Normals", normals.serializeEach(VecHelper::writeNBTCompound));
if (smoothing != null)
compound.put("Smoothing", smoothing.serializeEach(NBTHelper::intToCompound));
return compound;
}
@ -98,6 +116,8 @@ public class BezierConnection implements Iterable<BezierConnection.Segment> {
this(Couple.create(buffer::readBlockPos), Couple.create(() -> VecHelper.read(buffer)),
Couple.create(() -> VecHelper.read(buffer)), Couple.create(() -> VecHelper.read(buffer)),
buffer.readBoolean(), buffer.readBoolean());
if (buffer.readBoolean())
smoothing = Couple.create(buffer::readVarInt);
}
public void write(FriendlyByteBuf buffer) {
@ -107,6 +127,9 @@ public class BezierConnection implements Iterable<BezierConnection.Segment> {
normals.forEach(v -> VecHelper.write(v, buffer));
buffer.writeBoolean(primary);
buffer.writeBoolean(hasGirder);
buffer.writeBoolean(smoothing != null);
if (smoothing != null)
smoothing.forEach(buffer::writeVarInt);
}
public BlockPos getKey() {
@ -117,6 +140,16 @@ public class BezierConnection implements Iterable<BezierConnection.Segment> {
return primary;
}
public int yOffsetAt(Vec3 end) {
if (smoothing == null)
return 0;
if (TrackBlockEntityTilt.compareHandles(starts.getFirst(), end))
return smoothing.getFirst();
if (TrackBlockEntityTilt.compareHandles(starts.getSecond(), end))
return smoothing.getSecond();
return 0;
}
// Runtime information
public double getLength() {

View file

@ -38,6 +38,10 @@ public interface ITrackBlock {
public Vec3 getCurveStart(BlockGetter world, BlockPos pos, BlockState state, Vec3 axis);
public default int getYOffsetAt(BlockGetter world, BlockPos pos, BlockState state, Vec3 end) {
return 0;
}
public BlockState getBogeyAnchor(BlockGetter world, BlockPos pos, BlockState state); // should be on bogey side
public boolean trackEquals(BlockState state1, BlockState state2);
@ -71,10 +75,17 @@ public interface ITrackBlock {
.add(0, getElevationAtCenter(world, pos, state), 0);
List<DiscoveredLocation> list = new ArrayList<>();
TrackShape shape = state.getValue(TrackBlock.SHAPE);
getTrackAxes(world, pos, state).forEach(axis -> {
addToListIfConnected(connectedTo, list, (d, b) -> axis.scale(b ? d : -d)
.add(center), b -> shape.getNormal(), b -> world instanceof Level l ? l.dimension() : Level.OVERWORLD,
axis, null);
List<Vec3> trackAxes = getTrackAxes(world, pos, state);
trackAxes.forEach(axis -> {
BiFunction<Double, Boolean, Vec3> offsetFactory = (d, b) -> axis.scale(b ? d : -d)
.add(center);
Function<Boolean, ResourceKey<Level>> dimensionFactory =
b -> world instanceof Level l ? l.dimension() : Level.OVERWORLD;
Function<Vec3, Integer> yOffsetFactory = v -> getYOffsetAt(world, pos, state, v);
addToListIfConnected(connectedTo, list, offsetFactory, b -> shape.getNormal(), dimensionFactory,
yOffsetFactory, axis, null);
});
return list;
@ -82,22 +93,28 @@ public interface ITrackBlock {
public static void addToListIfConnected(@Nullable TrackNodeLocation fromEnd, Collection<DiscoveredLocation> list,
BiFunction<Double, Boolean, Vec3> offsetFactory, Function<Boolean, Vec3> normalFactory,
Function<Boolean, ResourceKey<Level>> dimensionFactory, Vec3 axis, BezierConnection viaTurn) {
Function<Boolean, ResourceKey<Level>> dimensionFactory, Function<Vec3, Integer> yOffsetFactory, Vec3 axis,
BezierConnection viaTurn) {
Vec3 firstOffset = offsetFactory.apply(0.5d, true);
DiscoveredLocation firstLocation =
new DiscoveredLocation(dimensionFactory.apply(true), offsetFactory.apply(0.5d, true)).viaTurn(viaTurn)
new DiscoveredLocation(dimensionFactory.apply(true), firstOffset).viaTurn(viaTurn)
.withNormal(normalFactory.apply(true))
.withDirection(axis);
.withDirection(axis)
.withYOffset(yOffsetFactory.apply(firstOffset));
Vec3 secondOffset = offsetFactory.apply(0.5d, false);
DiscoveredLocation secondLocation =
new DiscoveredLocation(dimensionFactory.apply(false), offsetFactory.apply(0.5d, false)).viaTurn(viaTurn)
new DiscoveredLocation(dimensionFactory.apply(false), secondOffset).viaTurn(viaTurn)
.withNormal(normalFactory.apply(false))
.withDirection(axis);
.withDirection(axis)
.withYOffset(yOffsetFactory.apply(secondOffset));
if (!firstLocation.dimension.equals(secondLocation.dimension)) {
firstLocation.forceNode();
secondLocation.forceNode();
}
boolean skipFirst = false;
boolean skipSecond = false;

View file

@ -67,6 +67,7 @@ public class TrackGraphHelper {
TrackNode frontNode = null;
TrackNode backNode = null;
double position = 0;
boolean singleTrackPiece = true;
for (DiscoveredLocation current : ends) {
Vec3 offset = current.getLocation()
@ -74,14 +75,19 @@ public class TrackGraphHelper {
.normalize()
.scale(length);
boolean forward = offset.distanceToSqr(axis.scale(-1)) < 1 / 4096f;
boolean backwards = offset.distanceToSqr(axis) < 1 / 4096f;
Vec3 compareOffset = offset.multiply(1, 0, 1)
.normalize();
boolean forward = compareOffset.distanceToSqr(axis.multiply(-1, 0, -1)
.normalize()) < 1 / 4096f;
boolean backwards = compareOffset.distanceToSqr(axis.multiply(1, 0, 1)
.normalize()) < 1 / 4096f;
if (!forward && !backwards)
continue;
DiscoveredLocation previous = null;
double distance = 0;
for (int i = 0; i < 100 && distance < 32; i++) {
DiscoveredLocation loc = current;
if (graph == null)
@ -89,6 +95,7 @@ public class TrackGraphHelper {
.getGraph(level, loc);
if (graph == null || graph.locateNode(loc) == null) {
singleTrackPiece = false;
Collection<DiscoveredLocation> list = ITrackBlock.walkConnectedTracks(level, loc, true);
for (DiscoveredLocation discoveredLocation : list) {
if (discoveredLocation == previous)
@ -121,6 +128,13 @@ public class TrackGraphHelper {
if (frontNode == null || backNode == null)
return null;
if (singleTrackPiece)
position = frontNode.getLocation()
.getLocation()
.distanceTo(backNode.getLocation()
.getLocation())
/ 2.0;
GraphLocation graphLocation = new GraphLocation();
graphLocation.edge = Couple.create(backNode.getLocation(), frontNode.getLocation());
graphLocation.position = position;
@ -143,6 +157,9 @@ public class TrackGraphHelper {
return null;
TrackNodeLocation targetLoc = new TrackNodeLocation(bc.starts.getSecond()).in(level);
if (bc.smoothing != null)
targetLoc.yOffsetPixels = bc.smoothing.getSecond();
for (DiscoveredLocation location : track.getConnected(level, pos, state, true, null)) {
TrackGraph graph = Create.RAILWAYS.sided(level)
.getGraph(level, location);

View file

@ -1,7 +1,6 @@
package com.simibubi.create.content.logistics.trains;
import java.util.UUID;
import java.util.function.Supplier;
import com.simibubi.create.CreateClient;
import com.simibubi.create.foundation.networking.SimplePacketBase;
@ -15,11 +14,9 @@ public abstract class TrackGraphPacket extends SimplePacketBase {
public boolean packetDeletesGraph;
@Override
public void handle(Supplier<Context> context) {
context.get()
.enqueueWork(() -> handle(CreateClient.RAILWAYS, CreateClient.RAILWAYS.getOrCreateGraph(graphId, netId)));
context.get()
.setPacketHandled(true);
public boolean handle(Context context) {
context.enqueueWork(() -> handle(CreateClient.RAILWAYS, CreateClient.RAILWAYS.getOrCreateGraph(graphId, netId)));
return true;
}
protected abstract void handle(GlobalRailwayManager manager, TrackGraph graph);

View file

@ -1,7 +1,5 @@
package com.simibubi.create.content.logistics.trains;
import java.util.function.Supplier;
import com.simibubi.create.Create;
import com.simibubi.create.foundation.networking.SimplePacketBase;
@ -26,19 +24,16 @@ public class TrackGraphRequestPacket extends SimplePacketBase {
}
@Override
public void handle(Supplier<Context> context) {
context.get()
.enqueueWork(() -> {
public boolean handle(Context context) {
context.enqueueWork(() -> {
for (TrackGraph trackGraph : Create.RAILWAYS.trackNetworks.values()) {
if (trackGraph.netId == netId) {
Create.RAILWAYS.sync.sendFullGraphTo(trackGraph, context.get()
.getSender());
break;
}
if (trackGraph.netId == netId) {
Create.RAILWAYS.sync.sendFullGraphTo(trackGraph, context.getSender());
break;
}
});
context.get()
.setPacketHandled(true);
}
});
return true;
}
}

View file

@ -7,7 +7,6 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.function.Supplier;
import com.simibubi.create.Create;
import com.simibubi.create.foundation.networking.AllPackets;
@ -45,39 +44,35 @@ public class TrackGraphRollCallPacket extends SimplePacketBase {
}
@Override
public void handle(Supplier<Context> context) {
context.get()
.enqueueWork(() -> {
public boolean handle(Context context) {
context.enqueueWork(() -> {
GlobalRailwayManager manager = Create.RAILWAYS.sided(null);
Set<UUID> unusedIds = new HashSet<>(manager.trackNetworks.keySet());
List<Integer> failedIds = new ArrayList<>();
Map<Integer, UUID> idByNetId = new HashMap<>();
manager.trackNetworks.forEach((uuid, g) -> idByNetId.put(g.netId, uuid));
GlobalRailwayManager manager = Create.RAILWAYS.sided(null);
Set<UUID> unusedIds = new HashSet<>(manager.trackNetworks.keySet());
List<Integer> failedIds = new ArrayList<>();
Map<Integer, UUID> idByNetId = new HashMap<>();
manager.trackNetworks.forEach((uuid, g) -> idByNetId.put(g.netId, uuid));
for (int i = 0; i < ints.length; i += 2) {
UUID uuid = idByNetId.get(ints[i]);
if (uuid == null) {
failedIds.add(ints[i]);
continue;
}
unusedIds.remove(uuid);
TrackGraph trackGraph = manager.trackNetworks.get(uuid);
if (trackGraph.getChecksum() == ints[i + 1])
continue;
Create.LOGGER.warn("Track network: " + uuid.toString()
.substring(0, 6) + " failed its checksum; Requesting refresh");
for (int i = 0; i < ints.length; i += 2) {
UUID uuid = idByNetId.get(ints[i]);
if (uuid == null) {
failedIds.add(ints[i]);
continue;
}
unusedIds.remove(uuid);
TrackGraph trackGraph = manager.trackNetworks.get(uuid);
if (trackGraph.getChecksum() == ints[i + 1])
continue;
Create.LOGGER.warn("Track network: " + uuid.toString()
.substring(0, 6) + " failed its checksum; Requesting refresh");
failedIds.add(ints[i]);
}
for (Integer failed : failedIds)
AllPackets.getChannel().sendToServer(new TrackGraphRequestPacket(failed));
for (UUID unused : unusedIds)
manager.trackNetworks.remove(unused);
});
context.get()
.setPacketHandled(true);
for (Integer failed : failedIds)
AllPackets.getChannel().sendToServer(new TrackGraphRequestPacket(failed));
for (UUID unused : unusedIds)
manager.trackNetworks.remove(unused);
});
return true;
}
}

View file

@ -19,13 +19,14 @@ import net.minecraft.world.phys.Vec3;
public class TrackNodeLocation extends Vec3i {
public ResourceKey<Level> dimension;
public int yOffsetPixels;
public TrackNodeLocation(Vec3 vec) {
this(vec.x, vec.y, vec.z);
}
public TrackNodeLocation(double p_121865_, double p_121866_, double p_121867_) {
super(Math.round(p_121865_ * 2), Math.floor(p_121866_ * 2), Math.round(p_121867_ * 2));
super(Math.round(p_121865_ * 2), Math.floor(p_121866_) * 2, Math.round(p_121867_ * 2));
}
public TrackNodeLocation in(Level level) {
@ -46,7 +47,7 @@ public class TrackNodeLocation extends Vec3i {
}
public Vec3 getLocation() {
return new Vec3(getX() / 2.0, getY() / 2.0, getZ() / 2.0);
return new Vec3(getX() / 2.0, getY() / 2.0 + yOffsetPixels / 16.0, getZ() / 2.0);
}
public ResourceKey<Level> getDimension() {
@ -60,18 +61,20 @@ public class TrackNodeLocation extends Vec3i {
}
public boolean equalsIgnoreDim(Object pOther) {
return super.equals(pOther);
return super.equals(pOther) && pOther instanceof TrackNodeLocation tnl && tnl.yOffsetPixels == yOffsetPixels;
}
@Override
public int hashCode() {
return (this.getY() + (this.getZ() * 31 + dimension.hashCode()) * 31) * 31 + this.getX();
return (getY() + ((getZ() + yOffsetPixels * 31) * 31 + dimension.hashCode()) * 31) * 31 + getX();
}
public CompoundTag write(DimensionPalette dimensions) {
CompoundTag c = NbtUtils.writeBlockPos(new BlockPos(this));
if (dimensions != null)
c.putInt("D", dimensions.encode(dimension));
if (yOffsetPixels != 0)
c.putInt("YO", yOffsetPixels);
return c;
}
@ -79,13 +82,15 @@ public class TrackNodeLocation extends Vec3i {
TrackNodeLocation location = fromPackedPos(NbtUtils.readBlockPos(tag));
if (dimensions != null)
location.dimension = dimensions.decode(tag.getInt("D"));
location.yOffsetPixels = tag.getInt("YO");
return location;
}
public void send(FriendlyByteBuf buffer, DimensionPalette dimensions) {
buffer.writeVarInt(this.getX());
buffer.writeShort(this.getY());
buffer.writeVarInt(this.getZ());
buffer.writeVarInt(getX());
buffer.writeShort(getY());
buffer.writeVarInt(getZ());
buffer.writeVarInt(yOffsetPixels);
buffer.writeVarInt(dimensions.encode(dimension));
}
@ -95,13 +100,14 @@ public class TrackNodeLocation extends Vec3i {
buffer.readShort(),
buffer.readVarInt()
));
location.yOffsetPixels = buffer.readVarInt();
location.dimension = dimensions.decode(buffer.readVarInt());
return location;
}
public Collection<BlockPos> allAdjacent() {
Set<BlockPos> set = new HashSet<>();
Vec3 vec3 = getLocation();
Vec3 vec3 = getLocation().subtract(0, yOffsetPixels / 16.0, 0);
double step = 1 / 8f;
for (int x : Iterate.positiveAndNegative)
for (int y : Iterate.positiveAndNegative)
@ -147,6 +153,11 @@ public class TrackNodeLocation extends Vec3i {
this.normal = normal;
return this;
}
public DiscoveredLocation withYOffset(int yOffsetPixels) {
this.yOffsetPixels = yOffsetPixels;
return this;
}
public DiscoveredLocation withDirection(Vec3 direction) {
this.direction = direction == null ? null : direction.normalize();

View file

@ -4,7 +4,6 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.function.Supplier;
import com.simibubi.create.CreateClient;
import com.simibubi.create.content.logistics.trains.IBogeyBlock;
@ -99,17 +98,15 @@ public class TrainPacket extends SimplePacketBase {
}
@Override
public void handle(Supplier<Context> context) {
context.get()
.enqueueWork(() -> {
Map<UUID, Train> trains = CreateClient.RAILWAYS.trains;
if (add)
trains.put(train.id, train);
else
trains.remove(trainId);
});
context.get()
.setPacketHandled(true);
public boolean handle(Context context) {
context.enqueueWork(() -> {
Map<UUID, Train> trains = CreateClient.RAILWAYS.trains;
if (add)
trains.put(train.id, train);
else
trains.remove(trainId);
});
return true;
}
}

View file

@ -1,7 +1,5 @@
package com.simibubi.create.content.logistics.trains.entity;
import java.util.function.Supplier;
import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.TrainHUD;
import com.simibubi.create.foundation.networking.SimplePacketBase;
@ -34,11 +32,9 @@ public class TrainPromptPacket extends SimplePacketBase {
}
@Override
public void handle(Supplier<Context> context) {
context.get()
.enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> this::apply));
context.get()
.setPacketHandled(true);
public boolean handle(Context context) {
context.enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> this::apply));
return true;
}
@OnlyIn(Dist.CLIENT)

View file

@ -1,7 +1,6 @@
package com.simibubi.create.content.logistics.trains.entity;
import java.util.UUID;
import java.util.function.Supplier;
import com.simibubi.create.Create;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionRelocationPacket;
@ -65,10 +64,9 @@ public class TrainRelocationPacket extends SimplePacketBase {
}
@Override
public void handle(Supplier<Context> context) {
Context ctx = context.get();
ctx.enqueueWork(() -> {
ServerPlayer sender = ctx.getSender();
public boolean handle(Context context) {
context.enqueueWork(() -> {
ServerPlayer sender = context.getSender();
Train train = Create.RAILWAYS.trains.get(trainId);
Entity entity = sender.level.getEntity(entityId);
@ -109,9 +107,8 @@ public class TrainRelocationPacket extends SimplePacketBase {
}
Create.LOGGER.warn(messagePrefix + train.name.getString() + ": relocation failed server-side");
});
ctx.setPacketHandled(true);
return true;
}
}

View file

@ -358,7 +358,7 @@ public class TravellingPoint {
return traveled;
}
private Double edgeTraversedFrom(TrackGraph graph, boolean forward, IEdgePointListener edgePointListener,
protected Double edgeTraversedFrom(TrackGraph graph, boolean forward, IEdgePointListener edgePointListener,
ITurnListener turnListener, double prevPos, double totalDistance) {
if (edge.isTurn())
turnListener.accept(Math.max(0, totalDistance), edge);

View file

@ -41,12 +41,13 @@ public class TrackObserverBlockEntity extends SmartBlockEntity implements ITrans
filtering.setLabel(Lang.translateDirect("logistics.train_observer.cargo_filter"));
}
private void onFilterChanged(ItemStack newFilter) {
private boolean onFilterChanged(ItemStack newFilter) {
if (level.isClientSide())
return;
return true;
TrackObserver observer = getObserver();
if (observer != null)
observer.setFilterAndNotify(level, newFilter);
return true;
}
@Override

View file

@ -4,7 +4,6 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.function.Supplier;
import com.google.common.collect.ImmutableList;
import com.simibubi.create.CreateClient;
@ -51,26 +50,24 @@ public class SignalEdgeGroupPacket extends SimplePacketBase {
}
@Override
public void handle(Supplier<Context> context) {
context.get()
.enqueueWork(() -> {
Map<UUID, SignalEdgeGroup> signalEdgeGroups = CreateClient.RAILWAYS.signalEdgeGroups;
int i = 0;
for (UUID id : ids) {
if (!add) {
signalEdgeGroups.remove(id);
continue;
}
SignalEdgeGroup group = new SignalEdgeGroup(id);
signalEdgeGroups.put(id, group);
if (colors.size() > i)
group.color = colors.get(i);
i++;
public boolean handle(Context context) {
context.enqueueWork(() -> {
Map<UUID, SignalEdgeGroup> signalEdgeGroups = CreateClient.RAILWAYS.signalEdgeGroups;
int i = 0;
for (UUID id : ids) {
if (!add) {
signalEdgeGroups.remove(id);
continue;
}
});
context.get()
.setPacketHandled(true);
SignalEdgeGroup group = new SignalEdgeGroup(id);
signalEdgeGroups.put(id, group);
if (colors.size() > i)
group.color = colors.get(i);
i++;
}
});
return true;
}
}

View file

@ -65,14 +65,16 @@ public class AssemblyScreen extends AbstractStationScreen {
toggleAssemblyButton.active = false;
toggleAssemblyButton.setToolTip(Lang.translateDirect("station.assemble_train"));
toggleAssemblyButton.withCallback(() -> {
AllPackets.getChannel().sendToServer(StationEditPacket.tryAssemble(blockEntity.getBlockPos()));
AllPackets.getChannel()
.sendToServer(StationEditPacket.tryAssemble(blockEntity.getBlockPos()));
});
quitAssembly = new IconButton(x + 73, by, AllIcons.I_DISABLE);
quitAssembly.active = true;
quitAssembly.setToolTip(Lang.translateDirect("station.cancel"));
quitAssembly.withCallback(() -> {
AllPackets.getChannel().sendToServer(StationEditPacket.configure(blockEntity.getBlockPos(), false, station.name));
AllPackets.getChannel()
.sendToServer(StationEditPacket.configure(blockEntity.getBlockPos(), false, station.name, null));
minecraft.setScreen(new StationScreen(blockEntity, station));
});
@ -90,7 +92,8 @@ public class AssemblyScreen extends AbstractStationScreen {
toggleAssemblyButton.active = blockEntity.bogeyCount > 0 || train != null;
if (train != null) {
AllPackets.getChannel().sendToServer(StationEditPacket.configure(blockEntity.getBlockPos(), false, station.name));
AllPackets.getChannel()
.sendToServer(StationEditPacket.configure(blockEntity.getBlockPos(), false, station.name, null));
minecraft.setScreen(new StationScreen(blockEntity, station));
for (Carriage carriage : train.carriages)
carriage.updateConductors();
@ -105,10 +108,12 @@ public class AssemblyScreen extends AbstractStationScreen {
toggleAssemblyButton.setToolTip(Lang.translateDirect("station.assemble_train"));
toggleAssemblyButton.setIcon(AllGuiTextures.I_ASSEMBLE_TRAIN);
toggleAssemblyButton.withCallback(() -> {
AllPackets.getChannel().sendToServer(StationEditPacket.tryAssemble(blockEntity.getBlockPos()));
AllPackets.getChannel()
.sendToServer(StationEditPacket.tryAssemble(blockEntity.getBlockPos()));
});
} else {
AllPackets.getChannel().sendToServer(StationEditPacket.configure(blockEntity.getBlockPos(), false, station.name));
AllPackets.getChannel()
.sendToServer(StationEditPacket.configure(blockEntity.getBlockPos(), false, station.name, null));
minecraft.setScreen(new StationScreen(blockEntity, station));
}
}
@ -128,8 +133,8 @@ public class AssemblyScreen extends AbstractStationScreen {
font.draw(ms, text, x + 97 - font.width(text) / 2, y + 47, 0x775B5B);
int offset = 0;
if (blockEntity.failedCarriageIndex != -1) {
font.draw(ms, Lang.translateDirect("station.carriage_number", blockEntity.failedCarriageIndex), x + 30, y + 67,
0x7A7A7A);
font.draw(ms, Lang.translateDirect("station.carriage_number", blockEntity.failedCarriageIndex), x + 30,
y + 67, 0x7A7A7A);
offset += 10;
}
font.drawWordWrap(lastAssemblyException.component, x + 30, y + 67 + offset, 134, 0x775B5B);
@ -158,7 +163,8 @@ public class AssemblyScreen extends AbstractStationScreen {
if (train != null) {
ResourceLocation iconId = iconTypes.get(iconTypeScroll.getState());
train.icon = TrainIconType.byId(iconId);
AllPackets.getChannel().sendToServer(new TrainEditPacket(train.id, "", iconId));
AllPackets.getChannel()
.sendToServer(new TrainEditPacket(train.id, "", iconId));
}
}

View file

@ -16,6 +16,7 @@ import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllItems;
import com.simibubi.create.AllSoundEvents;
import com.simibubi.create.Create;
import com.simibubi.create.content.contraptions.components.actors.DoorControlBehaviour;
import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
import com.simibubi.create.content.contraptions.components.structureMovement.ITransformableBlockEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.StructureTransform;
@ -80,6 +81,7 @@ import net.minecraftforge.network.PacketDistributor;
public class StationBlockEntity extends SmartBlockEntity implements ITransformableBlockEntity {
public TrackTargetingBehaviour<GlobalStation> edgePoint;
public DoorControlBehaviour doorControls;
public LerpedFloat flag;
protected int failedCarriageIndex;
@ -111,6 +113,7 @@ public class StationBlockEntity extends SmartBlockEntity implements ITransformab
@Override
public void addBehaviours(List<BlockEntityBehaviour> behaviours) {
behaviours.add(edgePoint = new TrackTargetingBehaviour<>(this, EdgePointType.STATION));
behaviours.add(doorControls = new DoorControlBehaviour(this));
behaviours.add(depotBehaviour = new DepotBehaviour(this).onlyAccepts(AllItems.SCHEDULE::isIn)
.withCallback(s -> applyAutoSchedule()));
depotBehaviour.addSubBehaviours(behaviours);

View file

@ -1,6 +1,7 @@
package com.simibubi.create.content.logistics.trains.management.edgePoint.station;
import com.simibubi.create.Create;
import com.simibubi.create.content.contraptions.components.actors.DoorControl;
import com.simibubi.create.content.logistics.trains.GraphLocation;
import com.simibubi.create.content.logistics.trains.entity.Train;
import com.simibubi.create.foundation.networking.BlockEntityConfigurationPacket;
@ -9,6 +10,7 @@ import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
@ -20,6 +22,7 @@ public class StationEditPacket extends BlockEntityConfigurationPacket<StationBlo
boolean dropSchedule;
boolean assemblyMode;
Boolean tryAssemble;
DoorControl doorControl;
String name;
public static StationEditPacket dropSchedule(BlockPos pos) {
@ -40,11 +43,12 @@ public class StationEditPacket extends BlockEntityConfigurationPacket<StationBlo
return packet;
}
public static StationEditPacket configure(BlockPos pos, boolean assemble, String name) {
public static StationEditPacket configure(BlockPos pos, boolean assemble, String name, DoorControl doorControl) {
StationEditPacket packet = new StationEditPacket(pos);
packet.assemblyMode = assemble;
packet.tryAssemble = null;
packet.name = name;
packet.doorControl = doorControl;
return packet;
}
@ -61,6 +65,9 @@ public class StationEditPacket extends BlockEntityConfigurationPacket<StationBlo
buffer.writeBoolean(dropSchedule);
if (dropSchedule)
return;
buffer.writeBoolean(doorControl != null);
if (doorControl != null)
buffer.writeVarInt(doorControl.ordinal());
buffer.writeBoolean(tryAssemble != null);
if (tryAssemble != null) {
buffer.writeBoolean(tryAssemble);
@ -76,6 +83,8 @@ public class StationEditPacket extends BlockEntityConfigurationPacket<StationBlo
dropSchedule = true;
return;
}
if (buffer.readBoolean())
doorControl = DoorControl.values()[Mth.clamp(buffer.readVarInt(), 0, DoorControl.values().length)];
name = "";
if (buffer.readBoolean()) {
tryAssemble = buffer.readBoolean();
@ -95,6 +104,9 @@ public class StationEditPacket extends BlockEntityConfigurationPacket<StationBlo
scheduleDropRequested(player, be);
return;
}
if (doorControl != null)
be.doorControls.set(doorControl);
if (!name.isBlank()) {
GlobalStation station = be.getStation();

View file

@ -8,7 +8,9 @@ import com.jozufozu.flywheel.core.PartialModel;
import com.mojang.blaze3d.platform.InputConstants;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllPartialModels;
import com.simibubi.create.content.contraptions.components.actors.DoorControl;
import com.simibubi.create.content.logistics.trains.entity.Carriage;
import com.simibubi.create.content.logistics.trains.entity.Train;
import com.simibubi.create.content.logistics.trains.entity.TrainIconType;
@ -16,9 +18,12 @@ import com.simibubi.create.foundation.gui.AllGuiTextures;
import com.simibubi.create.foundation.gui.AllIcons;
import com.simibubi.create.foundation.gui.UIRenderHelper;
import com.simibubi.create.foundation.gui.widget.IconButton;
import com.simibubi.create.foundation.gui.widget.Label;
import com.simibubi.create.foundation.gui.widget.ScrollInput;
import com.simibubi.create.foundation.networking.AllPackets;
import com.simibubi.create.foundation.utility.Components;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.Pair;
import com.simibubi.create.foundation.utility.animation.LerpedFloat;
import net.minecraft.ChatFormatting;
@ -37,6 +42,7 @@ public class StationScreen extends AbstractStationScreen {
private int leavingAnimation;
private LerpedFloat trainPosition;
private DoorControl doorControl;
private boolean switchingToAssemblyMode;
@ -47,6 +53,7 @@ public class StationScreen extends AbstractStationScreen {
trainPosition = LerpedFloat.linear()
.startWithValue(0);
switchingToAssemblyMode = false;
doorControl = be.doorControls.mode;
}
@Override
@ -88,8 +95,8 @@ public class StationScreen extends AbstractStationScreen {
dropScheduleButton = new IconButton(x + 73, y + 65, AllIcons.I_VIEW_SCHEDULE);
dropScheduleButton.active = false;
dropScheduleButton.visible = false;
dropScheduleButton
.withCallback(() -> AllPackets.getChannel().sendToServer(StationEditPacket.dropSchedule(blockEntity.getBlockPos())));
dropScheduleButton.withCallback(() -> AllPackets.getChannel()
.sendToServer(StationEditPacket.dropSchedule(blockEntity.getBlockPos())));
addRenderableWidget(dropScheduleButton);
onTextChanged = s -> trainNameBox.x = nameBoxX(s, trainNameBox);
@ -103,6 +110,11 @@ public class StationScreen extends AbstractStationScreen {
trainNameBox.active = false;
tickTrainDisplay();
Pair<ScrollInput, Label> doorControlWidgets =
DoorControl.createWidget(x + 35, y + 102, mode -> doorControl = mode, doorControl);
addRenderableWidget(doorControlWidgets.getFirst());
addRenderableWidget(doorControlWidgets.getSecond());
}
@Override
@ -192,12 +204,13 @@ public class StationScreen extends AbstractStationScreen {
}
boolean trainAtStation = trainPresent();
disassembleTrainButton.active = trainAtStation && blockEntity.trainCanDisassemble && blockEntity.edgePoint.isOrthogonal();
disassembleTrainButton.active =
trainAtStation && blockEntity.trainCanDisassemble && blockEntity.edgePoint.isOrthogonal();
dropScheduleButton.active = blockEntity.trainHasSchedule;
if (blockEntity.trainHasSchedule)
dropScheduleButton.setToolTip(
Lang.translateDirect(blockEntity.trainHasAutoSchedule ? "station.remove_auto_schedule" : "station.remove_schedule"));
dropScheduleButton.setToolTip(Lang.translateDirect(
blockEntity.trainHasAutoSchedule ? "station.remove_auto_schedule" : "station.remove_schedule"));
else
dropScheduleButton.getToolTip()
.clear();
@ -237,6 +250,8 @@ public class StationScreen extends AbstractStationScreen {
if (!nameBox.isFocused())
AllGuiTextures.STATION_EDIT_NAME.render(ms, nameBoxX(text, nameBox) + font.width(text) + 5, y + 1);
itemRenderer.renderGuiItem(AllBlocks.TRAIN_DOOR.asStack(), x + 14, y + 103);
Train train = displayedTrain.get();
if (train == null) {
MutableComponent header = Lang.translateDirect("station.idle");
@ -333,32 +348,38 @@ public class StationScreen extends AbstractStationScreen {
Train train = displayedTrain.get();
if (train != null && !trainNameBox.getValue()
.equals(train.name.getString()))
AllPackets.getChannel().sendToServer(new TrainEditPacket(train.id, trainNameBox.getValue(), train.icon.getId()));
AllPackets.getChannel()
.sendToServer(new TrainEditPacket(train.id, trainNameBox.getValue(), train.icon.getId()));
}
private void syncStationName() {
if (!nameBox.getValue()
.equals(station.name))
AllPackets.getChannel().sendToServer(StationEditPacket.configure(blockEntity.getBlockPos(), false, nameBox.getValue()));
AllPackets.getChannel()
.sendToServer(
StationEditPacket.configure(blockEntity.getBlockPos(), false, nameBox.getValue(), doorControl));
}
@Override
public void removed() {
super.removed();
AllPackets.getChannel()
.sendToServer(StationEditPacket.configure(blockEntity.getBlockPos(), switchingToAssemblyMode, nameBox.getValue()));
.sendToServer(StationEditPacket.configure(blockEntity.getBlockPos(), switchingToAssemblyMode,
nameBox.getValue(), doorControl));
Train train = displayedTrain.get();
if (train == null)
return;
if (!switchingToAssemblyMode)
AllPackets.getChannel().sendToServer(new TrainEditPacket(train.id, trainNameBox.getValue(), train.icon.getId()));
AllPackets.getChannel()
.sendToServer(new TrainEditPacket(train.id, trainNameBox.getValue(), train.icon.getId()));
else
blockEntity.imminentTrain = null;
}
@Override
protected PartialModel getFlag(float partialTicks) {
return blockEntity.flag.getValue(partialTicks) > 0.75f ? AllPartialModels.STATION_ON : AllPartialModels.STATION_OFF;
return blockEntity.flag.getValue(partialTicks) > 0.75f ? AllPartialModels.STATION_ON
: AllPartialModels.STATION_OFF;
}
}

View file

@ -1,7 +1,6 @@
package com.simibubi.create.content.logistics.trains.management.edgePoint.station;
import java.util.UUID;
import java.util.function.Supplier;
import com.simibubi.create.Create;
import com.simibubi.create.content.logistics.trains.entity.Train;
@ -43,10 +42,9 @@ public class TrainEditPacket extends SimplePacketBase {
}
@Override
public void handle(Supplier<Context> context) {
Context ctx = context.get();
ctx.enqueueWork(() -> {
ServerPlayer sender = ctx.getSender();
public boolean handle(Context context) {
context.enqueueWork(() -> {
ServerPlayer sender = context.getSender();
Level level = sender == null ? null : sender.level;
Train train = Create.RAILWAYS.sided(level).trains.get(id);
if (train == null)
@ -57,7 +55,7 @@ public class TrainEditPacket extends SimplePacketBase {
if (sender != null)
AllPackets.getChannel().send(PacketDistributor.ALL.noArg(), new TrainEditReturnPacket(id, name, iconType));
});
ctx.setPacketHandled(true);
return true;
}
public static class TrainEditReturnPacket extends TrainEditPacket {

View file

@ -1,7 +1,5 @@
package com.simibubi.create.content.logistics.trains.management.schedule;
import java.util.function.Supplier;
import com.simibubi.create.AllItems;
import com.simibubi.create.foundation.networking.SimplePacketBase;
@ -29,28 +27,25 @@ public class ScheduleEditPacket extends SimplePacketBase {
}
@Override
public void handle(Supplier<Context> context) {
context.get()
.enqueueWork(() -> {
ServerPlayer sender = context.get()
.getSender();
ItemStack mainHandItem = sender.getMainHandItem();
if (!AllItems.SCHEDULE.isIn(mainHandItem))
return;
CompoundTag tag = mainHandItem.getOrCreateTag();
if (schedule.entries.isEmpty()) {
tag.remove("Schedule");
if (tag.isEmpty())
mainHandItem.setTag(null);
} else
tag.put("Schedule", schedule.write());
sender.getCooldowns()
.addCooldown(mainHandItem.getItem(), 5);
});
context.get()
.setPacketHandled(true);
public boolean handle(Context context) {
context.enqueueWork(() -> {
ServerPlayer sender = context.getSender();
ItemStack mainHandItem = sender.getMainHandItem();
if (!AllItems.SCHEDULE.isIn(mainHandItem))
return;
CompoundTag tag = mainHandItem.getOrCreateTag();
if (schedule.entries.isEmpty()) {
tag.remove("Schedule");
if (tag.isEmpty())
mainHandItem.setTag(null);
} else
tag.put("Schedule", schedule.write());
sender.getCooldowns()
.addCooldown(mainHandItem.getItem(), 5);
});
return true;
}
}

View file

@ -1,7 +1,5 @@
package com.simibubi.create.content.logistics.trains.track;
import java.util.function.Supplier;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.networking.SimplePacketBase;
@ -34,10 +32,9 @@ public class PlaceExtendedCurvePacket extends SimplePacketBase {
}
@Override
public void handle(Supplier<Context> context) {
Context ctx = context.get();
ctx.enqueueWork(() -> {
ServerPlayer sender = ctx.getSender();
public boolean handle(Context context) {
context.enqueueWork(() -> {
ServerPlayer sender = context.getSender();
ItemStack stack = sender.getItemInHand(mainHand ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND);
if (!AllBlocks.TRACK.isIn(stack) || !stack.hasTag())
return;
@ -45,7 +42,7 @@ public class PlaceExtendedCurvePacket extends SimplePacketBase {
tag.putBoolean("ExtendCurve", true);
stack.setTag(tag);
});
ctx.setPacketHandled(true);
return true;
}
}

View file

@ -124,7 +124,7 @@ public class TrackBlock extends Block
protected void createBlockStateDefinition(Builder<Block, BlockState> p_49915_) {
super.createBlockStateDefinition(p_49915_.add(SHAPE, HAS_BE, WATERLOGGED));
}
@Override
public BlockPathTypes getAiPathNodeType(BlockState state, BlockGetter world, BlockPos pos, Mob entity) {
return BlockPathTypes.RAIL;
@ -208,7 +208,7 @@ public class TrackBlock extends Block
return;
withBlockEntityDo(pLevel, pPos, be -> {
be.cancelDrops = true;
be.removeInboundConnections();
be.removeInboundConnections(true);
});
}
@ -233,6 +233,7 @@ public class TrackBlock extends Block
@Override
public void tick(BlockState state, ServerLevel level, BlockPos pos, Random p_60465_) {
TrackPropagator.onRailAdded(level, pos, state);
withBlockEntityDo(level, pos, tbe -> tbe.tilt.undoSmoothing());
if (!state.getValue(SHAPE)
.isPortal())
connectToNether(level, pos, state);
@ -297,12 +298,14 @@ public class TrackBlock extends Block
Player player = level.getNearestPlayer(pos.getX(), pos.getY(), pos.getZ(), 10, Predicates.alwaysTrue());
if (player == null)
return;
player.displayClientMessage(Components.literal("<!> ").append(Lang.translateDirect("portal_track.failed"))
player.displayClientMessage(Components.literal("<!> ")
.append(Lang.translateDirect("portal_track.failed"))
.withStyle(ChatFormatting.GOLD), false);
MutableComponent component =
failPos != null ? Lang.translateDirect("portal_track." + fail, failPos.getX(), failPos.getY(), failPos.getZ())
: Lang.translateDirect("portal_track." + fail);
player.displayClientMessage(Components.literal(" - ").withStyle(ChatFormatting.GRAY)
MutableComponent component = failPos != null
? Lang.translateDirect("portal_track." + fail, failPos.getX(), failPos.getY(), failPos.getZ())
: Lang.translateDirect("portal_track." + fail);
player.displayClientMessage(Components.literal(" - ")
.withStyle(ChatFormatting.GRAY)
.append(component.withStyle(st -> st.withColor(0xFFD3B4))), false);
}
@ -361,6 +364,12 @@ public class TrackBlock extends Block
return state;
}
@Override
public int getYOffsetAt(BlockGetter world, BlockPos pos, BlockState state, Vec3 end) {
return getBlockEntityOptional(world, pos).map(tbe -> tbe.tilt.getYOffsetForAxisEnd(end))
.orElse(0);
}
@Override
public Collection<DiscoveredLocation> getConnected(BlockGetter worldIn, BlockPos pos, BlockState state,
boolean linear, TrackNodeLocation connectedTo) {
@ -378,8 +387,8 @@ public class TrackBlock extends Block
ITrackBlock.addToListIfConnected(connectedTo, list,
(d, b) -> axis.scale(b ? 0 : fromCenter ? -d : d)
.add(center),
b -> shape.getNormal(), b -> world instanceof Level l ? l.dimension() : Level.OVERWORLD, axis,
null);
b -> shape.getNormal(), b -> world instanceof Level l ? l.dimension() : Level.OVERWORLD, v -> 0,
axis, null);
} else
list = ITrackBlock.super.getConnected(world, pos, state, linear, connectedTo);
@ -395,7 +404,7 @@ public class TrackBlock extends Block
Map<BlockPos, BezierConnection> connections = trackTE.getConnections();
connections.forEach((connectedPos, bc) -> ITrackBlock.addToListIfConnected(connectedTo, list,
(d, b) -> d == 1 ? Vec3.atLowerCornerOf(bc.tePositions.get(b)) : bc.starts.get(b), bc.normals::get,
b -> world instanceof Level l ? l.dimension() : Level.OVERWORLD, null, bc));
b -> world instanceof Level l ? l.dimension() : Level.OVERWORLD, bc::yOffsetAt, null, bc));
if (trackTE.boundLocation == null || !(world instanceof ServerLevel level))
return list;
@ -421,7 +430,7 @@ public class TrackBlock extends Block
getTrackAxes(world, pos, state).forEach(axis -> {
ITrackBlock.addToListIfConnected(connectedTo, list, (d, b) -> (b ? axis : boundAxis).scale(d)
.add(b ? center : boundCenter), b -> (b ? shape : boundShape).getNormal(),
b -> b ? level.dimension() : otherLevel.dimension(), axis, null);
b -> b ? level.dimension() : otherLevel.dimension(), v -> 0, axis, null);
});
return list;
@ -444,8 +453,10 @@ public class TrackBlock extends Block
boolean removeBE = false;
if (pState.getValue(HAS_BE) && (!pState.is(pNewState.getBlock()) || !pNewState.getValue(HAS_BE))) {
BlockEntity blockEntity = pLevel.getBlockEntity(pPos);
if (blockEntity instanceof TrackBlockEntity && !pLevel.isClientSide)
((TrackBlockEntity) blockEntity).removeInboundConnections();
if (blockEntity instanceof TrackBlockEntity tbe && !pLevel.isClientSide) {
tbe.cancelDrops |= pNewState.getBlock() == this;
tbe.removeInboundConnections(true);
}
removeBE = true;
}
@ -468,7 +479,7 @@ public class TrackBlock extends Block
if (!entry.getValue()
.isInside(pos))
continue;
if (world.getBlockEntity(entry.getKey()) instanceof StationBlockEntity station)
if (world.getBlockEntity(entry.getKey())instanceof StationBlockEntity station)
if (station.trackClicked(player, hand, this, state, pos))
return InteractionResult.SUCCESS;
}
@ -484,7 +495,7 @@ public class TrackBlock extends Block
BlockPos girderPos = pPos.below()
.offset(vec3.z * side, 0, vec3.x * side);
BlockState girderState = pLevel.getBlockState(girderPos);
if (girderState.getBlock() instanceof GirderBlock girderBlock
if (girderState.getBlock()instanceof GirderBlock girderBlock
&& !blockTicks.hasScheduledTick(girderPos, girderBlock))
pLevel.scheduleTick(girderPos, girderBlock, 1);
}
@ -689,7 +700,7 @@ public class TrackBlock extends Block
Vec3 normal = null;
Vec3 offset = null;
if (bezierPoint != null && world.getBlockEntity(pos) instanceof TrackBlockEntity trackTE) {
if (bezierPoint != null && world.getBlockEntity(pos)instanceof TrackBlockEntity trackTE) {
BezierConnection bc = trackTE.connections.get(bezierPoint.curveTarget());
if (bc != null) {
double length = Mth.floor(bc.getLength() * 2);
@ -734,6 +745,16 @@ public class TrackBlock extends Block
msr.rotateCentered(Direction.UP, Mth.PI);
}
if (bezierPoint == null && world.getBlockEntity(pos)instanceof TrackBlockEntity trackTE && trackTE.isTilted()) {
double yOffset = 0;
for (BezierConnection bc : trackTE.connections.values())
yOffset += bc.starts.getFirst().y - pos.getY();
msr.centre()
.rotateX(-direction.getStep() * trackTE.tilt.smoothingAngle.get())
.unCentre()
.translate(0, yOffset / 2, 0);
}
return switch (type) {
case DUAL_SIGNAL -> AllPartialModels.TRACK_SIGNAL_DUAL_OVERLAY;
case OBSERVER -> AllPartialModels.TRACK_OBSERVER_OVERLAY;
@ -779,8 +800,7 @@ public class TrackBlock extends Block
public static class RenderProperties extends ReducedDestroyEffects implements MultiPosDestructionHandler {
@Override
@Nullable
public Set<BlockPos> getExtraPositions(ClientLevel level, BlockPos pos, BlockState blockState,
int progress) {
public Set<BlockPos> getExtraPositions(ClientLevel level, BlockPos pos, BlockState blockState, int progress) {
BlockEntity blockEntity = level.getBlockEntity(pos);
if (blockEntity instanceof TrackBlockEntity track) {
return new HashSet<>(track.connections.keySet());

View file

@ -5,6 +5,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
@ -44,6 +45,8 @@ import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.client.model.data.IModelData;
import net.minecraftforge.client.model.data.ModelDataMap;
import net.minecraftforge.fml.DistExecutor;
public class TrackBlockEntity extends SmartBlockEntity implements ITransformableBlockEntity, IMergeableBE {
@ -52,11 +55,13 @@ public class TrackBlockEntity extends SmartBlockEntity implements ITransformable
boolean cancelDrops;
public Pair<ResourceKey<Level>, BlockPos> boundLocation;
public TrackBlockEntityTilt tilt;
public TrackBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
super(type, pos, state);
connections = new HashMap<>();
setLazyTickRate(100);
tilt = new TrackBlockEntityTilt(this);
}
public Map<BlockPos, BezierConnection> getConnections() {
@ -70,6 +75,12 @@ public class TrackBlockEntity extends SmartBlockEntity implements ITransformable
registerToCurveInteraction();
}
@Override
public void tick() {
super.tick();
tilt.undoSmoothing();
}
@Override
public void lazyTick() {
for (BezierConnection connection : connections.values())
@ -103,8 +114,10 @@ public class TrackBlockEntity extends SmartBlockEntity implements ITransformable
continue;
}
if (!trackTE.connections.containsKey(worldPosition))
if (!trackTE.connections.containsKey(worldPosition)) {
trackTE.addConnection(bc.secondary());
trackTE.tilt.tryApplySmoothing();
}
}
for (BlockPos blockPos : invalid)
@ -121,6 +134,9 @@ public class TrackBlockEntity extends SmartBlockEntity implements ITransformable
}
public void removeConnection(BlockPos target) {
if (isTilted())
tilt.captureSmoothingHandles();
BezierConnection removed = connections.remove(target);
notifyUpdate();
@ -138,19 +154,19 @@ public class TrackBlockEntity extends SmartBlockEntity implements ITransformable
AllPackets.getChannel().send(packetTarget(), new RemoveBlockEntityPacket(worldPosition));
}
public void removeInboundConnections() {
public void removeInboundConnections(boolean dropAndDiscard) {
for (BezierConnection bezierConnection : connections.values()) {
BlockEntity blockEntity = level.getBlockEntity(bezierConnection.getKey());
if (!(blockEntity instanceof TrackBlockEntity))
if (!(level.getBlockEntity(bezierConnection.getKey())instanceof TrackBlockEntity tbe))
return;
TrackBlockEntity other = (TrackBlockEntity) blockEntity;
other.removeConnection(bezierConnection.tePositions.getFirst());
tbe.removeConnection(bezierConnection.tePositions.getFirst());
if (!dropAndDiscard)
continue;
if (!cancelDrops)
bezierConnection.spawnItems(level);
bezierConnection.spawnDestroyParticles(level);
}
AllPackets.getChannel().send(packetTarget(), new RemoveBlockEntityPacket(worldPosition));
if (dropAndDiscard)
AllPackets.getChannel().send(packetTarget(), new RemoveBlockEntityPacket(worldPosition));
}
public void bind(ResourceKey<Level> boundDimension, BlockPos boundLocation) {
@ -158,16 +174,22 @@ public class TrackBlockEntity extends SmartBlockEntity implements ITransformable
setChanged();
}
public boolean isTilted() {
return tilt.smoothingAngle.isPresent();
}
@Override
public void writeSafe(CompoundTag tag) {
super.writeSafe(tag);
writeTurns(tag);
writeTurns(tag, true);
}
@Override
protected void write(CompoundTag tag, boolean clientPacket) {
super.write(tag, clientPacket);
writeTurns(tag);
writeTurns(tag, false);
if (isTilted())
tag.putDouble("Smoothing", tilt.smoothingAngle.get());
if (boundLocation == null)
return;
tag.put("BoundLocation", NbtUtils.writeBlockPos(boundLocation.getSecond()));
@ -176,10 +198,11 @@ public class TrackBlockEntity extends SmartBlockEntity implements ITransformable
.toString());
}
private void writeTurns(CompoundTag tag) {
private void writeTurns(CompoundTag tag, boolean restored) {
ListTag listTag = new ListTag();
for (BezierConnection bezierConnection : connections.values())
listTag.add(bezierConnection.write(worldPosition));
listTag.add((restored ? tilt.restoreToOriginalCurve(bezierConnection.clone()) : bezierConnection)
.write(worldPosition));
tag.put("Connections", listTag);
}
@ -194,6 +217,13 @@ public class TrackBlockEntity extends SmartBlockEntity implements ITransformable
connections.put(connection.getKey(), connection);
}
boolean smoothingPreviously = tilt.smoothingAngle.isPresent();
tilt.smoothingAngle = Optional.ofNullable(tag.contains("Smoothing") ? tag.getDouble("Smoothing") : null);
if (smoothingPreviously != tilt.smoothingAngle.isPresent() && clientPacket) {
requestModelDataUpdate();
level.sendBlockUpdated(worldPosition, getBlockState(), getBlockState(), 16);
}
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> InstancedRenderDispatcher.enqueueUpdate(this));
if (hasInteractableConnections())
@ -233,6 +263,15 @@ public class TrackBlockEntity extends SmartBlockEntity implements ITransformable
@Override
public void transform(StructureTransform transform) {
Map<BlockPos, BezierConnection> restoredConnections = new HashMap<>();
for (Entry<BlockPos, BezierConnection> entry : connections.entrySet())
restoredConnections.put(entry.getKey(),
tilt.restoreToOriginalCurve(tilt.restoreToOriginalCurve(entry.getValue()
.secondary())
.secondary()));
connections = restoredConnections;
tilt.smoothingAngle = Optional.empty();
if (transform.rotationAxis != Axis.Y)
return;
@ -300,6 +339,15 @@ public class TrackBlockEntity extends SmartBlockEntity implements ITransformable
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> this::removeFromCurveInteractionUnsafe);
}
@Override
public IModelData getModelData() {
if (!isTilted())
return super.getModelData();
return new ModelDataMap.Builder()
.withInitial(TrackBlockEntityTilt.ASCENDING_PROPERTY, tilt.smoothingAngle.get())
.build();
}
@OnlyIn(Dist.CLIENT)
private void registerToCurveInteractionUnsafe() {
TrackBlockOutline.TRACKS_WITH_TURNS.get(level)

View file

@ -0,0 +1,236 @@
package com.simibubi.create.content.logistics.trains.track;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import com.simibubi.create.content.logistics.trains.BezierConnection;
import com.simibubi.create.content.logistics.trains.ITrackBlock;
import com.simibubi.create.content.logistics.trains.TrackNodeLocation;
import com.simibubi.create.content.logistics.trains.TrackPropagator;
import com.simibubi.create.foundation.utility.Couple;
import com.simibubi.create.foundation.utility.Pair;
import net.minecraft.core.BlockPos;
import net.minecraft.util.Mth;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.client.model.data.ModelProperty;
public class TrackBlockEntityTilt {
public static final ModelProperty<Double> ASCENDING_PROPERTY = new ModelProperty<>();
public Optional<Double> smoothingAngle;
private Couple<Pair<Vec3, Integer>> previousSmoothingHandles;
private TrackBlockEntity blockEntity;
public TrackBlockEntityTilt(TrackBlockEntity blockEntity) {
this.blockEntity = blockEntity;
smoothingAngle = Optional.empty();
}
public void tryApplySmoothing() {
if (smoothingAngle.isPresent())
return;
Couple<BezierConnection> discoveredSlopes = Couple.create(null, null);
Vec3 axis = null;
BlockState blockState = blockEntity.getBlockState();
BlockPos worldPosition = blockEntity.getBlockPos();
Level level = blockEntity.getLevel();
if (!(blockState.getBlock()instanceof ITrackBlock itb))
return;
List<Vec3> axes = itb.getTrackAxes(level, worldPosition, blockState);
if (axes.size() != 1)
return;
if (axes.get(0).y != 0)
return;
if (blockEntity.boundLocation != null)
return;
for (BezierConnection bezierConnection : blockEntity.connections.values()) {
if (bezierConnection.starts.getFirst().y == bezierConnection.starts.getSecond().y)
continue;
if (bezierConnection.axes.getSecond().y != 0)
continue;
Vec3 normedAxis = bezierConnection.axes.getFirst()
.normalize();
if (axis != null) {
if (discoveredSlopes.getSecond() != null)
return;
if (normedAxis.dot(axis) > -1 + 1 / 64.0)
return;
discoveredSlopes.setSecond(bezierConnection);
continue;
}
axis = normedAxis;
discoveredSlopes.setFirst(bezierConnection);
}
if (discoveredSlopes.either(Objects::isNull))
return;
if (discoveredSlopes.getFirst().starts.getSecond().y > discoveredSlopes.getSecond().starts.getSecond().y)
discoveredSlopes = discoveredSlopes.swap();
Couple<Vec3> lowStarts = discoveredSlopes.getFirst().starts;
Couple<Vec3> highStarts = discoveredSlopes.getSecond().starts;
Vec3 lowestPoint = lowStarts.getSecond();
Vec3 highestPoint = highStarts.getSecond();
if (lowestPoint.y > lowStarts.getFirst().y)
return;
if (highestPoint.y < highStarts.getFirst().y)
return;
blockEntity.removeInboundConnections(false);
blockEntity.connections.clear();
TrackPropagator.onRailRemoved(level, worldPosition, blockState);
double hDistance = discoveredSlopes.getFirst()
.getLength()
+ discoveredSlopes.getSecond()
.getLength();
Vec3 baseAxis = discoveredSlopes.getFirst().axes.getFirst();
double baseAxisLength = baseAxis.x != 0 && baseAxis.z != 0 ? Math.sqrt(2) : 1;
double vDistance = highestPoint.y - lowestPoint.y;
double m = vDistance / (hDistance);
Vec3 diff = highStarts.getFirst()
.subtract(lowStarts.getFirst());
boolean flipRotation = diff.dot(new Vec3(1, 0, 2).normalize()) <= 0;
smoothingAngle = Optional.of(Math.toDegrees(Mth.atan2(m, 1)) * (flipRotation ? -1 : 1));
int smoothingParam = Mth.clamp((int) (m * baseAxisLength * 16), 0, 15);
Couple<Integer> smoothingResult = Couple.create(0, smoothingParam);
Vec3 raisedOffset = diff.normalize()
.add(0, Mth.clamp(m, 0, 1 - 1 / 512.0), 0)
.normalize()
.scale(baseAxisLength);
highStarts.setFirst(lowStarts.getFirst()
.add(raisedOffset));
boolean first = true;
for (BezierConnection bezierConnection : discoveredSlopes) {
int smoothingToApply = smoothingResult.get(first);
if (bezierConnection.smoothing == null)
bezierConnection.smoothing = Couple.create(0, 0);
bezierConnection.smoothing.setFirst(smoothingToApply);
bezierConnection.axes.setFirst(bezierConnection.axes.getFirst()
.add(0, (first ? 1 : -1) * -m, 0)
.normalize());
first = false;
BlockPos otherPosition = bezierConnection.getKey();
BlockState otherState = level.getBlockState(otherPosition);
if (!(otherState.getBlock() instanceof TrackBlock))
continue;
level.setBlockAndUpdate(otherPosition, otherState.setValue(TrackBlock.HAS_BE, true));
BlockEntity otherBE = level.getBlockEntity(otherPosition);
if (otherBE instanceof TrackBlockEntity tbe) {
blockEntity.addConnection(bezierConnection);
tbe.addConnection(bezierConnection.secondary());
}
}
}
public void captureSmoothingHandles() {
boolean first = true;
previousSmoothingHandles = Couple.create(null, null);
for (BezierConnection bezierConnection : blockEntity.connections.values()) {
previousSmoothingHandles.set(first, Pair.of(bezierConnection.starts.getFirst(),
bezierConnection.smoothing == null ? 0 : bezierConnection.smoothing.getFirst()));
first = false;
}
}
public void undoSmoothing() {
if (smoothingAngle.isEmpty())
return;
if (previousSmoothingHandles == null)
return;
if (blockEntity.connections.size() == 2)
return;
BlockState blockState = blockEntity.getBlockState();
BlockPos worldPosition = blockEntity.getBlockPos();
Level level = blockEntity.getLevel();
List<BezierConnection> validConnections = new ArrayList<>();
for (BezierConnection bezierConnection : blockEntity.connections.values()) {
BlockPos otherPosition = bezierConnection.getKey();
BlockEntity otherBE = level.getBlockEntity(otherPosition);
if (otherBE instanceof TrackBlockEntity tbe && tbe.connections.containsKey(worldPosition))
validConnections.add(bezierConnection);
}
blockEntity.removeInboundConnections(false);
TrackPropagator.onRailRemoved(level, worldPosition, blockState);
blockEntity.connections.clear();
smoothingAngle = Optional.empty();
for (BezierConnection bezierConnection : validConnections) {
blockEntity.addConnection(restoreToOriginalCurve(bezierConnection));
BlockPos otherPosition = bezierConnection.getKey();
BlockState otherState = level.getBlockState(otherPosition);
if (!(otherState.getBlock() instanceof TrackBlock))
continue;
level.setBlockAndUpdate(otherPosition, otherState.setValue(TrackBlock.HAS_BE, true));
BlockEntity otherBE = level.getBlockEntity(otherPosition);
if (otherBE instanceof TrackBlockEntity tbe)
tbe.addConnection(bezierConnection.secondary());
}
blockEntity.notifyUpdate();
previousSmoothingHandles = null;
TrackPropagator.onRailAdded(level, worldPosition, blockState);
}
public BezierConnection restoreToOriginalCurve(BezierConnection bezierConnection) {
if (bezierConnection.smoothing != null) {
bezierConnection.smoothing.setFirst(0);
if (bezierConnection.smoothing.getFirst() == 0 && bezierConnection.smoothing.getSecond() == 0)
bezierConnection.smoothing = null;
}
Vec3 raisedStart = bezierConnection.starts.getFirst();
bezierConnection.starts.setFirst(new TrackNodeLocation(raisedStart).getLocation());
bezierConnection.axes.setFirst(bezierConnection.axes.getFirst()
.multiply(1, 0, 1)
.normalize());
return bezierConnection;
}
public int getYOffsetForAxisEnd(Vec3 end) {
if (smoothingAngle.isEmpty())
return 0;
for (BezierConnection bezierConnection : blockEntity.connections.values())
if (compareHandles(bezierConnection.starts.getFirst(), end))
return bezierConnection.yOffsetAt(end);
if (previousSmoothingHandles == null)
return 0;
for (Pair<Vec3, Integer> handle : previousSmoothingHandles)
if (handle != null && compareHandles(handle.getFirst(), end))
return handle.getSecond();
return 0;
}
public static boolean compareHandles(Vec3 handle1, Vec3 handle2) {
return new TrackNodeLocation(handle1).getLocation()
.multiply(1, 0, 1)
.distanceToSqr(new TrackNodeLocation(handle2).getLocation()
.multiply(1, 0, 1)) < 1 / 512f;
}
}

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