Merge branch 'mc1.15/dev' into mc1.16/dev

This commit is contained in:
simibubi 2020-11-26 00:57:29 +01:00
commit e8edbcdb11
96 changed files with 1682 additions and 480 deletions

View file

@ -1,6 +1,6 @@
<p align="center"><img src="https://i.imgur.com/35JmqWB.gif" alt="Logo" width="100"></p> <p align="center"><img src="https://i.imgur.com/35JmqWB.gif" alt="Logo" width="100"></p>
<h1 align="center">Create<br> <h1 align="center">Create<br>
<a href="https://www.patreon.com/simibubi"><img src="https://img.shields.io/badge/Supporters-40-ff5733" alt="Patreon"></a> <a href="https://www.patreon.com/simibubi"><img src="https://img.shields.io/badge/Supporters-50+-ff5733" alt="Patreon"></a>
<a href="https://www.curseforge.com/minecraft/mc-mods/create/files"><img src="https://img.shields.io/badge/Available%20for-MC%201.14,%201.15-c70039" alt="Supported Versions"></a> <a href="https://www.curseforge.com/minecraft/mc-mods/create/files"><img src="https://img.shields.io/badge/Available%20for-MC%201.14,%201.15-c70039" alt="Supported Versions"></a>
<a href="https://github.com/Creators-of-Create/Create/blob/master/LICENSE"><img src="https://img.shields.io/github/license/Creators-of-Create/Create?style=flat&color=900c3f" alt="License"></a> <a href="https://github.com/Creators-of-Create/Create/blob/master/LICENSE"><img src="https://img.shields.io/github/license/Creators-of-Create/Create?style=flat&color=900c3f" alt="License"></a>
<a href="https://discord.gg/hmaD7Se"><img src="https://img.shields.io/discord/620934202875183104?color=844685&label=Feedback%20%26%20Help&style=flat" alt="Discord"></a> <a href="https://discord.gg/hmaD7Se"><img src="https://img.shields.io/discord/620934202875183104?color=844685&label=Feedback%20%26%20Help&style=flat" alt="Discord"></a>

View file

@ -58,6 +58,8 @@ ecf4a72411870bfdbf8a59469b114cd77621c343 assets/create/blockstates/copper_tiles.
3df0d5d5170a2f6cbab0f8a9bc8f2d64229589af assets/create/blockstates/creative_crate.json 3df0d5d5170a2f6cbab0f8a9bc8f2d64229589af assets/create/blockstates/creative_crate.json
da3f1203dd0b0096ce19e09705060a0ed0478bee assets/create/blockstates/creative_fluid_tank.json da3f1203dd0b0096ce19e09705060a0ed0478bee assets/create/blockstates/creative_fluid_tank.json
f0031f5e970b3d5695472ed384950b8631b015ed assets/create/blockstates/creative_motor.json f0031f5e970b3d5695472ed384950b8631b015ed assets/create/blockstates/creative_motor.json
24ee16e3dadb3e0221afce7af37643494f471fb0 assets/create/blockstates/crimson_window.json
3e6cd0945390b390b963474f7cf708e2dcba631c assets/create/blockstates/crimson_window_pane.json
fe2f78b94c20944399101e7369e2d43324297fb6 assets/create/blockstates/crushing_wheel.json fe2f78b94c20944399101e7369e2d43324297fb6 assets/create/blockstates/crushing_wheel.json
a1dd6cb3daa97ea871290ef7b178d28b564ee2a2 assets/create/blockstates/crushing_wheel_controller.json a1dd6cb3daa97ea871290ef7b178d28b564ee2a2 assets/create/blockstates/crushing_wheel_controller.json
b1126c191877cff86b4e2de83e1fcbd151451cb7 assets/create/blockstates/cuckoo_clock.json b1126c191877cff86b4e2de83e1fcbd151451cb7 assets/create/blockstates/cuckoo_clock.json
@ -137,7 +139,7 @@ fc652317e03b57c76e23a805da16a28d15254029 assets/create/blockstates/fancy_scoria_
fc9ac0a7e7191b93516719455a17177fa6524ecc assets/create/blockstates/fancy_weathered_limestone_bricks_slab.json fc9ac0a7e7191b93516719455a17177fa6524ecc assets/create/blockstates/fancy_weathered_limestone_bricks_slab.json
b2a7c321b1795f20e7433f81a55ce4683de081b8 assets/create/blockstates/fancy_weathered_limestone_bricks_stairs.json b2a7c321b1795f20e7433f81a55ce4683de081b8 assets/create/blockstates/fancy_weathered_limestone_bricks_stairs.json
8e532856c3c2b4e4e59c65a2a81a694e35d14658 assets/create/blockstates/fancy_weathered_limestone_bricks_wall.json 8e532856c3c2b4e4e59c65a2a81a694e35d14658 assets/create/blockstates/fancy_weathered_limestone_bricks_wall.json
3d97226b5e8d8f70ed08e45e78db1faf78d5e28b assets/create/blockstates/fluid_pipe.json 6e9589feb7fab2ac3bed5b4d70be383dfd7e9d7c assets/create/blockstates/fluid_pipe.json
f0eaab18e16c4f3f65ebf3b55b08f0dc445720fe assets/create/blockstates/fluid_tank.json f0eaab18e16c4f3f65ebf3b55b08f0dc445720fe assets/create/blockstates/fluid_tank.json
5408d92ab02af86539ac42971d4033545970bb3a assets/create/blockstates/fluid_valve.json 5408d92ab02af86539ac42971d4033545970bb3a assets/create/blockstates/fluid_valve.json
e9da1794b6ece7f9aa8bcb43d42c23a55446133b assets/create/blockstates/flywheel.json e9da1794b6ece7f9aa8bcb43d42c23a55446133b assets/create/blockstates/flywheel.json
@ -322,6 +324,7 @@ c8467d55bc22d2e2256b8b732c06c9fdc64d336f assets/create/blockstates/polished_weat
5d811eab3c5e8411f98e2ea98d93d35955ce18fc assets/create/blockstates/polished_weathered_limestone_slab.json 5d811eab3c5e8411f98e2ea98d93d35955ce18fc assets/create/blockstates/polished_weathered_limestone_slab.json
acec6cdebe772ca72de94a85d98199e827495acb assets/create/blockstates/polished_weathered_limestone_stairs.json acec6cdebe772ca72de94a85d98199e827495acb assets/create/blockstates/polished_weathered_limestone_stairs.json
ad721e3911f48c61c3639edac1896680a31451ff assets/create/blockstates/polished_weathered_limestone_wall.json ad721e3911f48c61c3639edac1896680a31451ff assets/create/blockstates/polished_weathered_limestone_wall.json
3bb571d0a2597907bf3a30686b4bfa0841ac990a assets/create/blockstates/portable_fluid_interface.json
1b70b4e5792dccd2110b84e209016ac258005e28 assets/create/blockstates/portable_storage_interface.json 1b70b4e5792dccd2110b84e209016ac258005e28 assets/create/blockstates/portable_storage_interface.json
8296d43d5f1c2113012d127038fb319af83aaee4 assets/create/blockstates/powered_latch.json 8296d43d5f1c2113012d127038fb319af83aaee4 assets/create/blockstates/powered_latch.json
e8b0a401c10d1ba67ed71ba31bd5f9bc28571b65 assets/create/blockstates/powered_toggle_latch.json e8b0a401c10d1ba67ed71ba31bd5f9bc28571b65 assets/create/blockstates/powered_toggle_latch.json
@ -330,7 +333,7 @@ e8b0a401c10d1ba67ed71ba31bd5f9bc28571b65 assets/create/blockstates/powered_toggl
d06cd9a1101b18d306a786320aab12018b1325d6 assets/create/blockstates/purple_sail.json d06cd9a1101b18d306a786320aab12018b1325d6 assets/create/blockstates/purple_sail.json
92957119abd5fbcca36a113b2a80255fd70fc303 assets/create/blockstates/purple_seat.json 92957119abd5fbcca36a113b2a80255fd70fc303 assets/create/blockstates/purple_seat.json
61035f8afe75ff7bbd291da5d8690bcbebe679eb assets/create/blockstates/purple_valve_handle.json 61035f8afe75ff7bbd291da5d8690bcbebe679eb assets/create/blockstates/purple_valve_handle.json
5d1b30c2bab556f57c78e7780fd445b08f541a50 assets/create/blockstates/radial_chassis.json 4bb26546ac954604a0317b059f2c36a1123772cb assets/create/blockstates/radial_chassis.json
45877c4d90a7185c2f304edbd67379d800920439 assets/create/blockstates/red_sail.json 45877c4d90a7185c2f304edbd67379d800920439 assets/create/blockstates/red_sail.json
da1b08387af7afa0855ee8d040f620c01f20660a assets/create/blockstates/red_seat.json da1b08387af7afa0855ee8d040f620c01f20660a assets/create/blockstates/red_seat.json
722fc77bbf387af8a4016e42cbf9501d2b968881 assets/create/blockstates/red_valve_handle.json 722fc77bbf387af8a4016e42cbf9501d2b968881 assets/create/blockstates/red_valve_handle.json
@ -371,6 +374,8 @@ a2454400b1cf9889f70aebdc89c52a1be25f543c assets/create/blockstates/tiled_glass_p
a8094531617e27a545c4815ab2062bf0ffca3633 assets/create/blockstates/turntable.json a8094531617e27a545c4815ab2062bf0ffca3633 assets/create/blockstates/turntable.json
69dfe8afaa8eb6105dae9f76ab8b7847bf90b8c6 assets/create/blockstates/vertical_framed_glass.json 69dfe8afaa8eb6105dae9f76ab8b7847bf90b8c6 assets/create/blockstates/vertical_framed_glass.json
c4db76b9d36cfb098df0d158cb6f8b82768ebe14 assets/create/blockstates/vertical_framed_glass_pane.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
d995547bcd71603ba7378d8998098e462030bfd0 assets/create/blockstates/water_wheel.json d995547bcd71603ba7378d8998098e462030bfd0 assets/create/blockstates/water_wheel.json
f182669f7547964f9f2ef67916568556870def7b assets/create/blockstates/weathered_limestone.json f182669f7547964f9f2ef67916568556870def7b assets/create/blockstates/weathered_limestone.json
27e6740834c0f673acc3531371512daa6dcab025 assets/create/blockstates/weathered_limestone_bricks.json 27e6740834c0f673acc3531371512daa6dcab025 assets/create/blockstates/weathered_limestone_bricks.json
@ -392,17 +397,17 @@ a3a11524cd3515fc01d905767b4b7ea782adaf03 assets/create/blockstates/yellow_seat.j
6801fa1f466f172700e573e5b8ee8ee5f9ca4583 assets/create/blockstates/yellow_valve_handle.json 6801fa1f466f172700e573e5b8ee8ee5f9ca4583 assets/create/blockstates/yellow_valve_handle.json
7f39521b211441f5c3e06d60c5978cebe16cacfb assets/create/blockstates/zinc_block.json 7f39521b211441f5c3e06d60c5978cebe16cacfb assets/create/blockstates/zinc_block.json
b7181bcd8182b2f17088e5aa881f374c9c65470c assets/create/blockstates/zinc_ore.json b7181bcd8182b2f17088e5aa881f374c9c65470c assets/create/blockstates/zinc_ore.json
04f295b9cbe610bb3664e956437ae68d2a0776ad assets/create/lang/en_ud.json 9b9e9c1867c7cc0247d36212df26e90e8b91ee8f assets/create/lang/en_ud.json
3912eddc0fdb76afe08961c9d9ad9fe776fbbef5 assets/create/lang/en_us.json 40261df65cf82a5e15069412ba98521897b6a42c assets/create/lang/en_us.json
66e50a9482f186f3b0b066bcc7a8d6194b5892b4 assets/create/lang/unfinished/de_de.json 51577716a7ad7a72b06e81b3ee8bd0ed4e96901f assets/create/lang/unfinished/de_de.json
d0adae002c2ca46ad24d4f08037308334c239c69 assets/create/lang/unfinished/fr_fr.json b57edbe8a697a923ad993a7fb4dc9867bd88c038 assets/create/lang/unfinished/fr_fr.json
98b6589d85a68eb4460a7d2da96816b026436c14 assets/create/lang/unfinished/it_it.json f4a1427a07cd88ae8566b9217e8a33be6ee5c941 assets/create/lang/unfinished/it_it.json
9a9477f8257367993760fbc9e4b65a2d8190b868 assets/create/lang/unfinished/ja_jp.json bb4ce8e1274f35f5157d042f5d9831532325d921 assets/create/lang/unfinished/ja_jp.json
e9e466d962ccba589d6d14e37c82e98076a3e614 assets/create/lang/unfinished/ko_kr.json cd166b00cfbdd6c92e21e809bb6278e0fbba2628 assets/create/lang/unfinished/ko_kr.json
9e8277f247b069bb45fd45b086a5138ec160847f assets/create/lang/unfinished/nl_nl.json d400b7c2850ddcc9fa1d96df28c2b3494b908d16 assets/create/lang/unfinished/nl_nl.json
707ec25a7f45dd3dca8b96d4031b38d1be64f840 assets/create/lang/unfinished/pt_br.json e5d52c146688f5c0d7acf570d41d73969677a1a3 assets/create/lang/unfinished/pt_br.json
f645e781db3e254d64ea4b20a553e713bfca3610 assets/create/lang/unfinished/ru_ru.json 33ad047f902748c14188b9f67c79c7e9e571567e assets/create/lang/unfinished/ru_ru.json
1e8a48a6ba2d7ec7947c312835c332e869757526 assets/create/lang/unfinished/zh_cn.json de21d615b547f01107d3d562d8d0f2afe14e18be assets/create/lang/unfinished/zh_cn.json
487a511a01b2a4531fb672f917922312db78f958 assets/create/models/block/acacia_window.json 487a511a01b2a4531fb672f917922312db78f958 assets/create/models/block/acacia_window.json
b48060cba1a382f373a05bf0039054053eccf076 assets/create/models/block/acacia_window_pane_noside.json b48060cba1a382f373a05bf0039054053eccf076 assets/create/models/block/acacia_window_pane_noside.json
3066db1bf03cffa1a9c7fbacf47ae586632f4eb3 assets/create/models/block/acacia_window_pane_noside_alt.json 3066db1bf03cffa1a9c7fbacf47ae586632f4eb3 assets/create/models/block/acacia_window_pane_noside_alt.json
@ -492,7 +497,7 @@ bc23a91f300e46761bb14c597fad39c3d414e84d assets/create/models/block/brass_belt_f
dfc6250e28e12ff193a45891978ec50c406fc0c2 assets/create/models/block/brass_belt_funnel__pulling.json dfc6250e28e12ff193a45891978ec50c406fc0c2 assets/create/models/block/brass_belt_funnel__pulling.json
5409325494780afe32e6e30377314e2992ca4aa5 assets/create/models/block/brass_belt_funnel__pushing.json 5409325494780afe32e6e30377314e2992ca4aa5 assets/create/models/block/brass_belt_funnel__pushing.json
97410a12b7c1461f88fb633f26ff566a0636b627 assets/create/models/block/brass_belt_funnel__retracted.json 97410a12b7c1461f88fb633f26ff566a0636b627 assets/create/models/block/brass_belt_funnel__retracted.json
2b1ca994d2feec8321fdb0388028c20d40326eb7 assets/create/models/block/brass_block.json 5adb8b446817eee3a31971d708320c7104d6bbd8 assets/create/models/block/brass_block.json
2e67c147d7c69aabd9ab9f7aa80f60671d5a03aa assets/create/models/block/brass_casing.json 2e67c147d7c69aabd9ab9f7aa80f60671d5a03aa assets/create/models/block/brass_casing.json
838e7ab4c0c9d89eacfa078daf64995e505db896 assets/create/models/block/brass_funnel.json 838e7ab4c0c9d89eacfa078daf64995e505db896 assets/create/models/block/brass_funnel.json
6099ba0366065d15d3b2821474850a1ae85485ea assets/create/models/block/brass_funnel_powered.json 6099ba0366065d15d3b2821474850a1ae85485ea assets/create/models/block/brass_funnel_powered.json
@ -547,6 +552,12 @@ feed58a4ad7d7a9e855f0cd7b3fc720616120b4b assets/create/models/block/creative_sin
59c43cc18525792ca96026c966076f52cf7ebef7 assets/create/models/block/creative_top_window_nw.json 59c43cc18525792ca96026c966076f52cf7ebef7 assets/create/models/block/creative_top_window_nw.json
a6eea01609266b757342984889af16234ecd5189 assets/create/models/block/creative_top_window_se.json a6eea01609266b757342984889af16234ecd5189 assets/create/models/block/creative_top_window_se.json
6e1d2fb66291f2a3e3a213f43b47fb9760cb959f assets/create/models/block/creative_top_window_sw.json 6e1d2fb66291f2a3e3a213f43b47fb9760cb959f assets/create/models/block/creative_top_window_sw.json
8390ebba3a149135c21a3e48fcc84660eea5f766 assets/create/models/block/crimson_window.json
5e0c0ac8b2d222bb359a84a1f179c54c823ad5b8 assets/create/models/block/crimson_window_pane_noside.json
19503fe4a6eec4d250efb1a7a4fe53fd1035b429 assets/create/models/block/crimson_window_pane_noside_alt.json
14a14ab7c1a812a5ac8e282747f125461bf6b1d5 assets/create/models/block/crimson_window_pane_post.json
b9e6d8befe3f2281413288e0350425987256e238 assets/create/models/block/crimson_window_pane_side.json
bcbfa40524cff0314d9e764a64f90f2095d14064 assets/create/models/block/crimson_window_pane_side_alt.json
68843a02a32c156afad85830877b83f9b51c5147 assets/create/models/block/cyan_sail.json 68843a02a32c156afad85830877b83f9b51c5147 assets/create/models/block/cyan_sail.json
6704782830b3d872321e895b6903709c18e3778f assets/create/models/block/cyan_seat.json 6704782830b3d872321e895b6903709c18e3778f assets/create/models/block/cyan_seat.json
f45ef4a5f0aa8482d493661673b1c0ab6d061157 assets/create/models/block/cyan_valve_handle.json f45ef4a5f0aa8482d493661673b1c0ab6d061157 assets/create/models/block/cyan_valve_handle.json
@ -1116,6 +1127,12 @@ d13df8a5920c5778d98081fb0e97f045e2fd46a2 assets/create/models/block/vertical_fra
a5938ddd48109f067a19a90a0f9abab655c18821 assets/create/models/block/vertical_framed_glass_pane_post.json a5938ddd48109f067a19a90a0f9abab655c18821 assets/create/models/block/vertical_framed_glass_pane_post.json
41645919ece236df5804a5a73ef682720194de34 assets/create/models/block/vertical_framed_glass_pane_side.json 41645919ece236df5804a5a73ef682720194de34 assets/create/models/block/vertical_framed_glass_pane_side.json
8bc0abaabdc62d0c27730dba7eb6da54607b7e96 assets/create/models/block/vertical_framed_glass_pane_side_alt.json 8bc0abaabdc62d0c27730dba7eb6da54607b7e96 assets/create/models/block/vertical_framed_glass_pane_side_alt.json
c6c7067a760d8c787841a72c8048172fb534d8c5 assets/create/models/block/warped_window.json
01a1034b3bad86f23874b045c5eceb0f1078d6d9 assets/create/models/block/warped_window_pane_noside.json
51179b8e4e3d91cfb6fbeb08e1920afc2c16c237 assets/create/models/block/warped_window_pane_noside_alt.json
82b11c5dbd3ffdbbd129c4b4244487a8f3256f33 assets/create/models/block/warped_window_pane_post.json
b3682b275994e1dac31d56b56f3f3c1e3b2962d7 assets/create/models/block/warped_window_pane_side.json
0b1c6b66d22338e0152a62f869475d734029611e assets/create/models/block/warped_window_pane_side_alt.json
867c400d32bc2242d041bf650149fced6e7104ed assets/create/models/block/weathered_limestone.json 867c400d32bc2242d041bf650149fced6e7104ed assets/create/models/block/weathered_limestone.json
0235f7c186a5cb6c5081c4bbddb2e5bb0af76c93 assets/create/models/block/weathered_limestone_bricks.json 0235f7c186a5cb6c5081c4bbddb2e5bb0af76c93 assets/create/models/block/weathered_limestone_bricks.json
a569dd152c6a52281fe5ca704fa439768ca9b485 assets/create/models/block/weathered_limestone_bricks_slab.json a569dd152c6a52281fe5ca704fa439768ca9b485 assets/create/models/block/weathered_limestone_bricks_slab.json
@ -1211,6 +1228,8 @@ f56bf22324faf8958eaef4d94b958f1108d52e5a assets/create/models/item/copper_tiles.
7b333dea353afaa27b182aedc647c9e9e34e92ef assets/create/models/item/creative_crate.json 7b333dea353afaa27b182aedc647c9e9e34e92ef assets/create/models/item/creative_crate.json
f7d06c52c3ca8c22ad67f5741471f06ac22e7fcb assets/create/models/item/creative_fluid_tank.json f7d06c52c3ca8c22ad67f5741471f06ac22e7fcb assets/create/models/item/creative_fluid_tank.json
5b39403f6c81f05e566b621b62e267267de47c41 assets/create/models/item/creative_motor.json 5b39403f6c81f05e566b621b62e267267de47c41 assets/create/models/item/creative_motor.json
5680d7cee347c46bb29db8c77dc33f234a7eba41 assets/create/models/item/crimson_window.json
cdcc4c773bdda431e2aef26e83c061db36e66bae assets/create/models/item/crimson_window_pane.json
6281a7439c92459761893835f91fde25467fae76 assets/create/models/item/crushed_brass.json 6281a7439c92459761893835f91fde25467fae76 assets/create/models/item/crushed_brass.json
cd148cb7e881091ecce2390dac0d9f545573c91c assets/create/models/item/crushed_copper_ore.json cd148cb7e881091ecce2390dac0d9f545573c91c assets/create/models/item/crushed_copper_ore.json
5b701661c7b847dfe5b4cbc854b48f128f90090c assets/create/models/item/crushed_gold_ore.json 5b701661c7b847dfe5b4cbc854b48f128f90090c assets/create/models/item/crushed_gold_ore.json
@ -1480,6 +1499,7 @@ e95125318055b8557afd7d108488cf0bdd81fe49 assets/create/models/item/polished_scor
68fb04f7a89c8117bb641e347df9bfc1f1248335 assets/create/models/item/polished_weathered_limestone_slab.json 68fb04f7a89c8117bb641e347df9bfc1f1248335 assets/create/models/item/polished_weathered_limestone_slab.json
6d92ee7112aa20e8a1adfe73d8933031c299bed1 assets/create/models/item/polished_weathered_limestone_stairs.json 6d92ee7112aa20e8a1adfe73d8933031c299bed1 assets/create/models/item/polished_weathered_limestone_stairs.json
d98a1d479dff88d7a6f084f2c9de8fbbf80961ef assets/create/models/item/polished_weathered_limestone_wall.json d98a1d479dff88d7a6f084f2c9de8fbbf80961ef assets/create/models/item/polished_weathered_limestone_wall.json
0e5638cdbf04d7af2222ec15fbe1d960385ea237 assets/create/models/item/portable_fluid_interface.json
3bc60b0d9884c2ee0f1dd530e90fceb699eea737 assets/create/models/item/portable_storage_interface.json 3bc60b0d9884c2ee0f1dd530e90fceb699eea737 assets/create/models/item/portable_storage_interface.json
417c301eb7e54f14c564975570f59d048cc88987 assets/create/models/item/powdered_obsidian.json 417c301eb7e54f14c564975570f59d048cc88987 assets/create/models/item/powdered_obsidian.json
1e501c1f2e9250aaaadcf17db62646d08177d4e1 assets/create/models/item/powered_latch.json 1e501c1f2e9250aaaadcf17db62646d08177d4e1 assets/create/models/item/powered_latch.json
@ -1538,6 +1558,8 @@ fb24881c4e92bbb7ffa54a71e0af6b1c66d84829 assets/create/models/item/turntable.jso
5e331da9d4086412f5722923e3008246ed286a00 assets/create/models/item/vertical_framed_glass_pane.json 5e331da9d4086412f5722923e3008246ed286a00 assets/create/models/item/vertical_framed_glass_pane.json
00c2929de9b7171656bea74e1a6d694c6a45b075 assets/create/models/item/vertical_gearbox.json 00c2929de9b7171656bea74e1a6d694c6a45b075 assets/create/models/item/vertical_gearbox.json
2d4a31321cc13f62f5fd73aabdc5fd97e635bfbc assets/create/models/item/wand_of_symmetry.json 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
ae20383b0b0806431d0fdd8ffdd16fe2b0cc61ad assets/create/models/item/water_wheel.json ae20383b0b0806431d0fdd8ffdd16fe2b0cc61ad assets/create/models/item/water_wheel.json
1d097a315c2817d16c241c86f66bd48e5e52f4b4 assets/create/models/item/weathered_limestone.json 1d097a315c2817d16c241c86f66bd48e5e52f4b4 assets/create/models/item/weathered_limestone.json
fcc8ab312989ec485e2d86b856d81dbafaf0e930 assets/create/models/item/weathered_limestone_bricks.json fcc8ab312989ec485e2d86b856d81dbafaf0e930 assets/create/models/item/weathered_limestone_bricks.json
@ -1694,6 +1716,7 @@ ccd49c33260333ba850d0b843c4913cb6371eee9 data/create/advancements/recipes/create
ca21e2192a2fea0f112764f96c928d337762158b data/create/advancements/recipes/create.base/crafting/kinetics/pink_seat_from_other_seat.json ca21e2192a2fea0f112764f96c928d337762158b data/create/advancements/recipes/create.base/crafting/kinetics/pink_seat_from_other_seat.json
6c11444884679c4dd03d43f5893fca5cdc271915 data/create/advancements/recipes/create.base/crafting/kinetics/pink_valve_handle_from_other_valve_handle.json 6c11444884679c4dd03d43f5893fca5cdc271915 data/create/advancements/recipes/create.base/crafting/kinetics/pink_valve_handle_from_other_valve_handle.json
960d03f13b383fca0d9b7d3a2885da346d97c4ef data/create/advancements/recipes/create.base/crafting/kinetics/piston_extension_pole.json 960d03f13b383fca0d9b7d3a2885da346d97c4ef data/create/advancements/recipes/create.base/crafting/kinetics/piston_extension_pole.json
164563947ebd951d36a839ee0787714b104ba090 data/create/advancements/recipes/create.base/crafting/kinetics/portable_fluid_interface.json
3190b3800152879614127c7cd2616e5607f1a0b1 data/create/advancements/recipes/create.base/crafting/kinetics/portable_storage_interface.json 3190b3800152879614127c7cd2616e5607f1a0b1 data/create/advancements/recipes/create.base/crafting/kinetics/portable_storage_interface.json
02258b70f1db3d91f0ccb5a5ffd362349f8f359d data/create/advancements/recipes/create.base/crafting/kinetics/propeller.json 02258b70f1db3d91f0ccb5a5ffd362349f8f359d data/create/advancements/recipes/create.base/crafting/kinetics/propeller.json
d2a430820a87c24104729eede57628c6a92b277e data/create/advancements/recipes/create.base/crafting/kinetics/purple_seat.json d2a430820a87c24104729eede57628c6a92b277e data/create/advancements/recipes/create.base/crafting/kinetics/purple_seat.json
@ -1806,6 +1829,8 @@ c31a4d1eacc892a0248315270a12c0b49f5edc63 data/create/advancements/recipes/create
b873bd961cd865866a6f5035bee583a400073a3c data/create/advancements/recipes/create.palettes/chiseled_scoria_from_scoria_stonecutting.json b873bd961cd865866a6f5035bee583a400073a3c data/create/advancements/recipes/create.palettes/chiseled_scoria_from_scoria_stonecutting.json
0ace6bef40eab8e365959e529a16cd04d15adfe6 data/create/advancements/recipes/create.palettes/chiseled_weathered_limestone_from_weathered_limestone_stonecutting.json 0ace6bef40eab8e365959e529a16cd04d15adfe6 data/create/advancements/recipes/create.palettes/chiseled_weathered_limestone_from_weathered_limestone_stonecutting.json
b4651c8202331483e82b28b04edc6cd97e62ad1d data/create/advancements/recipes/create.palettes/crafting/palettes/dark_scoria.json b4651c8202331483e82b28b04edc6cd97e62ad1d data/create/advancements/recipes/create.palettes/crafting/palettes/dark_scoria.json
9a587cd39af620df5bf25ff0143108c6be9597f5 data/create/advancements/recipes/create.palettes/crimson_window.json
b2813566e6715c2d377dd4ef461b012cae7eb190 data/create/advancements/recipes/create.palettes/crimson_window_pane.json
25991d5667252d551e02c4fbbfa27ebf4353d28d data/create/advancements/recipes/create.palettes/dark_oak_window.json 25991d5667252d551e02c4fbbfa27ebf4353d28d data/create/advancements/recipes/create.palettes/dark_oak_window.json
4819383b1a7885b4401fdc25955d2c51f75b6236 data/create/advancements/recipes/create.palettes/dark_oak_window_pane.json 4819383b1a7885b4401fdc25955d2c51f75b6236 data/create/advancements/recipes/create.palettes/dark_oak_window_pane.json
ebd6413d530325eef6fcf42a0ee0ac840c1f7366 data/create/advancements/recipes/create.palettes/dark_scoria_bricks_from_dark_scoria_stonecutting.json ebd6413d530325eef6fcf42a0ee0ac840c1f7366 data/create/advancements/recipes/create.palettes/dark_scoria_bricks_from_dark_scoria_stonecutting.json
@ -2141,6 +2166,8 @@ ab0cacba05f8def9cc91b993d464c297babf6fc3 data/create/advancements/recipes/create
d40c7ce6b79630ace624d17b92667286998d93bc data/create/advancements/recipes/create.palettes/tiled_glass_pane.json d40c7ce6b79630ace624d17b92667286998d93bc data/create/advancements/recipes/create.palettes/tiled_glass_pane.json
24fafe59013a3e0439a73ea4e0cef114fc9a8e4b data/create/advancements/recipes/create.palettes/vertical_framed_glass_from_glass_colorless_stonecutting.json 24fafe59013a3e0439a73ea4e0cef114fc9a8e4b data/create/advancements/recipes/create.palettes/vertical_framed_glass_from_glass_colorless_stonecutting.json
cd5ee73117872ee98434be1d24b4f271f7e94a48 data/create/advancements/recipes/create.palettes/vertical_framed_glass_pane.json cd5ee73117872ee98434be1d24b4f271f7e94a48 data/create/advancements/recipes/create.palettes/vertical_framed_glass_pane.json
f26d1a1ee183b1b19d018fbdefc70f0bf29b41d0 data/create/advancements/recipes/create.palettes/warped_window.json
faf33c9c630eecab88bb969e3b9f7fd9e9f6ccf6 data/create/advancements/recipes/create.palettes/warped_window_pane.json
ef0d351d13f7e9c633581b537c59bddc1fa4c3a4 data/create/advancements/recipes/create.palettes/weathered_limestone_bricks_from_weathered_limestone_stonecutting.json ef0d351d13f7e9c633581b537c59bddc1fa4c3a4 data/create/advancements/recipes/create.palettes/weathered_limestone_bricks_from_weathered_limestone_stonecutting.json
1c931e15af3e5b5f78a0a62b8c159fdf9f0d7f3e data/create/advancements/recipes/create.palettes/weathered_limestone_bricks_slab.json 1c931e15af3e5b5f78a0a62b8c159fdf9f0d7f3e data/create/advancements/recipes/create.palettes/weathered_limestone_bricks_slab.json
bba639941526cc23570e328e0b5e2a5545667219 data/create/advancements/recipes/create.palettes/weathered_limestone_bricks_slab_from_weathered_limestone_bricks_stonecutting.json bba639941526cc23570e328e0b5e2a5545667219 data/create/advancements/recipes/create.palettes/weathered_limestone_bricks_slab_from_weathered_limestone_bricks_stonecutting.json
@ -2243,6 +2270,8 @@ c013613df278f6e8b4c9dad5f16e0ec6c3e992e3 data/create/loot_tables/blocks/copper_t
b160899aa785dc54d8c6cc095337f70b81f3e44f data/create/loot_tables/blocks/creative_crate.json b160899aa785dc54d8c6cc095337f70b81f3e44f data/create/loot_tables/blocks/creative_crate.json
51d66e32581b87beb871d99b93cb45d45eada8dd data/create/loot_tables/blocks/creative_fluid_tank.json 51d66e32581b87beb871d99b93cb45d45eada8dd data/create/loot_tables/blocks/creative_fluid_tank.json
d8f2f8921b9200b1d9476a77ee1be32c25308ac3 data/create/loot_tables/blocks/creative_motor.json d8f2f8921b9200b1d9476a77ee1be32c25308ac3 data/create/loot_tables/blocks/creative_motor.json
08b427aea85e467d7fe58d0e691de428dd64da7f data/create/loot_tables/blocks/crimson_window.json
ba084fc3c680c9dea0d03fc664a831dfed18e52e data/create/loot_tables/blocks/crimson_window_pane.json
c28fa42746a4d5ca2f824001b67e58673810169e data/create/loot_tables/blocks/crushing_wheel.json c28fa42746a4d5ca2f824001b67e58673810169e data/create/loot_tables/blocks/crushing_wheel.json
205f5899101262f31f5c1a88bb7d954918d08d04 data/create/loot_tables/blocks/crushing_wheel_controller.json 205f5899101262f31f5c1a88bb7d954918d08d04 data/create/loot_tables/blocks/crushing_wheel_controller.json
d370ee874b5b6b98e9a8c368218fe61f644d956d data/create/loot_tables/blocks/cuckoo_clock.json d370ee874b5b6b98e9a8c368218fe61f644d956d data/create/loot_tables/blocks/cuckoo_clock.json
@ -2507,6 +2536,7 @@ c7029af40b6f5dd2cd8f2ae7dfb89b37074624e6 data/create/loot_tables/blocks/polished
93f7be402a8088d33a94954572e111bcd71f11c8 data/create/loot_tables/blocks/polished_weathered_limestone_slab.json 93f7be402a8088d33a94954572e111bcd71f11c8 data/create/loot_tables/blocks/polished_weathered_limestone_slab.json
6ef650c723d409c7a678ffac45212e22e37581c0 data/create/loot_tables/blocks/polished_weathered_limestone_stairs.json 6ef650c723d409c7a678ffac45212e22e37581c0 data/create/loot_tables/blocks/polished_weathered_limestone_stairs.json
58715bc033e4740dbb754f91c93a22b9d06828e6 data/create/loot_tables/blocks/polished_weathered_limestone_wall.json 58715bc033e4740dbb754f91c93a22b9d06828e6 data/create/loot_tables/blocks/polished_weathered_limestone_wall.json
ac945ab9e78d52daff38b9c288824ec6f643b23a data/create/loot_tables/blocks/portable_fluid_interface.json
fbe98efcb1a5970b6795fdbbb671fee704c0945f data/create/loot_tables/blocks/portable_storage_interface.json fbe98efcb1a5970b6795fdbbb671fee704c0945f data/create/loot_tables/blocks/portable_storage_interface.json
6a46f00d9de7050eb9748d5dbed182caa6b29949 data/create/loot_tables/blocks/powered_latch.json 6a46f00d9de7050eb9748d5dbed182caa6b29949 data/create/loot_tables/blocks/powered_latch.json
a3fb7d3e3bf9dc73ce754002f10c469d57db1f71 data/create/loot_tables/blocks/powered_toggle_latch.json a3fb7d3e3bf9dc73ce754002f10c469d57db1f71 data/create/loot_tables/blocks/powered_toggle_latch.json
@ -2556,6 +2586,8 @@ e999969f05d2625e61757aa82092d232b99f6e0a data/create/loot_tables/blocks/tiled_gl
7b66ad2c48449bafd0cdbd086ac41218cb73a814 data/create/loot_tables/blocks/turntable.json 7b66ad2c48449bafd0cdbd086ac41218cb73a814 data/create/loot_tables/blocks/turntable.json
028e293b5cd694017962f67dc80dba719f904e28 data/create/loot_tables/blocks/vertical_framed_glass.json 028e293b5cd694017962f67dc80dba719f904e28 data/create/loot_tables/blocks/vertical_framed_glass.json
d0156602dd5f4a274c293df67e19374820c72890 data/create/loot_tables/blocks/vertical_framed_glass_pane.json d0156602dd5f4a274c293df67e19374820c72890 data/create/loot_tables/blocks/vertical_framed_glass_pane.json
1afc5ede08e72221e33910603fa7acd0b3c7a2ee data/create/loot_tables/blocks/warped_window.json
f334fd2b9a92b0646674239e7e34e142fe2c5fad data/create/loot_tables/blocks/warped_window_pane.json
2883c63ceb1273009dbf91cb0693756cadf79a1a data/create/loot_tables/blocks/water_wheel.json 2883c63ceb1273009dbf91cb0693756cadf79a1a data/create/loot_tables/blocks/water_wheel.json
611d6195db52c074de484ec52d7ac9eb96b4ff10 data/create/loot_tables/blocks/weathered_limestone.json 611d6195db52c074de484ec52d7ac9eb96b4ff10 data/create/loot_tables/blocks/weathered_limestone.json
c1f379baad36a20fc767be094db10480a0378184 data/create/loot_tables/blocks/weathered_limestone_bricks.json c1f379baad36a20fc767be094db10480a0378184 data/create/loot_tables/blocks/weathered_limestone_bricks.json
@ -2706,7 +2738,8 @@ af871a02d363a619fff8e9dde753aa417b265a80 data/create/recipes/crafting/kinetics/p
840dc5aac716e3d1b79883e8db4bf56f2dc427f9 data/create/recipes/crafting/kinetics/pink_seat_from_other_seat.json 840dc5aac716e3d1b79883e8db4bf56f2dc427f9 data/create/recipes/crafting/kinetics/pink_seat_from_other_seat.json
7e73bcde2b599f1ae5a241dd707c8ab6ce8c5a6e data/create/recipes/crafting/kinetics/pink_valve_handle_from_other_valve_handle.json 7e73bcde2b599f1ae5a241dd707c8ab6ce8c5a6e data/create/recipes/crafting/kinetics/pink_valve_handle_from_other_valve_handle.json
5399c3496a90bed9428c48fdd334ad4f763cbf9a data/create/recipes/crafting/kinetics/piston_extension_pole.json 5399c3496a90bed9428c48fdd334ad4f763cbf9a data/create/recipes/crafting/kinetics/piston_extension_pole.json
0b09786f6d9823c6eddc91c3a6837377690dde49 data/create/recipes/crafting/kinetics/portable_storage_interface.json a8e996bed77d3d20725f9d592c250392b3adb106 data/create/recipes/crafting/kinetics/portable_fluid_interface.json
7ed5699349faf2981228769c873057105a5ea3ea data/create/recipes/crafting/kinetics/portable_storage_interface.json
16199a6729005a279854cb1838401f6e73bdebae data/create/recipes/crafting/kinetics/propeller.json 16199a6729005a279854cb1838401f6e73bdebae data/create/recipes/crafting/kinetics/propeller.json
76ba751b65d312d1b34229d76fff2111b593091a data/create/recipes/crafting/kinetics/purple_seat.json 76ba751b65d312d1b34229d76fff2111b593091a data/create/recipes/crafting/kinetics/purple_seat.json
e6c462d64e1de9c7fca95f9c9a25b8d1575979da data/create/recipes/crafting/kinetics/purple_seat_from_other_seat.json e6c462d64e1de9c7fca95f9c9a25b8d1575979da data/create/recipes/crafting/kinetics/purple_seat_from_other_seat.json
@ -2787,6 +2820,8 @@ fe95f8f5f15edb0a5ff8da5a4757c9f8910b51bd data/create/recipes/crafting/palettes/d
5c47ac2e2b596439a684126fef7265f13de2379b data/create/recipes/crafting/schematics/schematic_and_quill.json 5c47ac2e2b596439a684126fef7265f13de2379b data/create/recipes/crafting/schematics/schematic_and_quill.json
9fb943be76c51a24aa9d8a09de5b7bd17b44ab08 data/create/recipes/crafting/schematics/schematic_table.json 9fb943be76c51a24aa9d8a09de5b7bd17b44ab08 data/create/recipes/crafting/schematics/schematic_table.json
1a810338ea15ab5ac2f37e87579c56f72b2b371b data/create/recipes/crafting/schematics/schematicannon.json 1a810338ea15ab5ac2f37e87579c56f72b2b371b data/create/recipes/crafting/schematics/schematicannon.json
4629d9a1a8a98a6b5b8b82c4507ca9e321c3a210 data/create/recipes/crimson_window.json
72cffde4281a1e34d77aa91c847e811833b68f21 data/create/recipes/crimson_window_pane.json
3da7a3cdb84f44e259b5399a94ddfbf94ebebd37 data/create/recipes/crushing/blaze_rod.json 3da7a3cdb84f44e259b5399a94ddfbf94ebebd37 data/create/recipes/crushing/blaze_rod.json
5878767e89be5a522b8f28d6a2d7b2f8566cf0dd data/create/recipes/crushing/brass_block.json 5878767e89be5a522b8f28d6a2d7b2f8566cf0dd data/create/recipes/crushing/brass_block.json
b83ef0af844ca068e0353330b8273bace5b6a8c3 data/create/recipes/crushing/coal_ore.json b83ef0af844ca068e0353330b8273bace5b6a8c3 data/create/recipes/crushing/coal_ore.json
@ -3289,6 +3324,8 @@ e2c1774577aeb0756fb1d092245d9d77e40ba5f8 data/create/recipes/splashing/yellow_co
39bd4bcaad003edbe035c91ffde61c51ee1edb87 data/create/recipes/tiled_glass_pane.json 39bd4bcaad003edbe035c91ffde61c51ee1edb87 data/create/recipes/tiled_glass_pane.json
7c6778a30bb670762c3a410cb19d1effc55a7063 data/create/recipes/vertical_framed_glass_from_glass_colorless_stonecutting.json 7c6778a30bb670762c3a410cb19d1effc55a7063 data/create/recipes/vertical_framed_glass_from_glass_colorless_stonecutting.json
dc6093427210bd7034a0e2184f6a1630c7b33b3e data/create/recipes/vertical_framed_glass_pane.json dc6093427210bd7034a0e2184f6a1630c7b33b3e data/create/recipes/vertical_framed_glass_pane.json
40ec72d571002206c276aec5de72459155e043ce data/create/recipes/warped_window.json
8f4b0a3cfb0073f1414bf18c0d4e5e751c4a9185 data/create/recipes/warped_window_pane.json
f75f25d3259dd51c29bee6ada2a4540a7a2bbeab data/create/recipes/weathered_limestone_bricks_from_weathered_limestone_stonecutting.json f75f25d3259dd51c29bee6ada2a4540a7a2bbeab data/create/recipes/weathered_limestone_bricks_from_weathered_limestone_stonecutting.json
f58ef5eb552fc7dcd89f30aa4231286ecef5e00a data/create/recipes/weathered_limestone_bricks_slab.json f58ef5eb552fc7dcd89f30aa4231286ecef5e00a data/create/recipes/weathered_limestone_bricks_slab.json
ca9b163b3aaa526d6c3b070c2a7e50a56a38c6f4 data/create/recipes/weathered_limestone_bricks_slab_from_weathered_limestone_bricks_stonecutting.json ca9b163b3aaa526d6c3b070c2a7e50a56a38c6f4 data/create/recipes/weathered_limestone_bricks_slab_from_weathered_limestone_bricks_stonecutting.json
@ -3320,7 +3357,7 @@ d2dc4ff179ef7b2aa9276455c196e15d44aa95a8 data/create/tags/items/crushed_ores.jso
abbe5d7cc9d1705509257888154ed7ca23292586 data/create/tags/items/upright_on_belt.json abbe5d7cc9d1705509257888154ed7ca23292586 data/create/tags/items/upright_on_belt.json
50936b211d94167a35ec78c89954082a336b6269 data/create/tags/items/valve_handles.json 50936b211d94167a35ec78c89954082a336b6269 data/create/tags/items/valve_handles.json
16bcb8fcbe9170c2c11f1ca8d99d8b36cd812bbd data/forge/tags/blocks/glass/colorless.json 16bcb8fcbe9170c2c11f1ca8d99d8b36cd812bbd data/forge/tags/blocks/glass/colorless.json
81ced867d24ec814942909965dd4576eff1db685 data/forge/tags/blocks/glass_panes.json 81d3eb40b048160fcc2d6bb7ff12b49276297efd data/forge/tags/blocks/glass_panes.json
4b700ee8aa748c2ec70c29ef1589844879c0deae data/forge/tags/blocks/ores.json 4b700ee8aa748c2ec70c29ef1589844879c0deae data/forge/tags/blocks/ores.json
4a0b13a9835106de9a1dd0a71a02372abb48e7b6 data/forge/tags/blocks/ores/copper.json 4a0b13a9835106de9a1dd0a71a02372abb48e7b6 data/forge/tags/blocks/ores/copper.json
d5ea262a0f5fb210612d22521818e26cf08e591a data/forge/tags/blocks/ores/zinc.json d5ea262a0f5fb210612d22521818e26cf08e591a data/forge/tags/blocks/ores/zinc.json
@ -3331,7 +3368,7 @@ f6c8f34ceb475546dba5cc6ff288863ea795d20b data/forge/tags/blocks/storage_blocks/c
d9ffc62a496946fc4848934e7c0a6e917337f8be data/forge/tags/items/beacon_payment.json d9ffc62a496946fc4848934e7c0a6e917337f8be data/forge/tags/items/beacon_payment.json
05ca51cdc60a5e109b5a0e3b782de13d34ebcb24 data/forge/tags/items/cobblestone.json 05ca51cdc60a5e109b5a0e3b782de13d34ebcb24 data/forge/tags/items/cobblestone.json
16bcb8fcbe9170c2c11f1ca8d99d8b36cd812bbd data/forge/tags/items/glass/colorless.json 16bcb8fcbe9170c2c11f1ca8d99d8b36cd812bbd data/forge/tags/items/glass/colorless.json
81ced867d24ec814942909965dd4576eff1db685 data/forge/tags/items/glass_panes.json 81d3eb40b048160fcc2d6bb7ff12b49276297efd data/forge/tags/items/glass_panes.json
d9ffc62a496946fc4848934e7c0a6e917337f8be data/forge/tags/items/ingots.json d9ffc62a496946fc4848934e7c0a6e917337f8be data/forge/tags/items/ingots.json
2dfd21017cb51d4bdc18d977a7d16f103cc3a985 data/forge/tags/items/ingots/brass.json 2dfd21017cb51d4bdc18d977a7d16f103cc3a985 data/forge/tags/items/ingots/brass.json
8e0ca32df10a50544f54fbe3dbfe485971b23315 data/forge/tags/items/ingots/copper.json 8e0ca32df10a50544f54fbe3dbfe485971b23315 data/forge/tags/items/ingots/copper.json
@ -3353,7 +3390,7 @@ ff1900963bc4cd8ceffa78d58ef1952ceacb2fb7 data/forge/tags/items/storage_blocks/br
f6c8f34ceb475546dba5cc6ff288863ea795d20b data/forge/tags/items/storage_blocks/copper.json f6c8f34ceb475546dba5cc6ff288863ea795d20b data/forge/tags/items/storage_blocks/copper.json
7f71a774800111e50b42de0e6159ed2d2a807d32 data/forge/tags/items/storage_blocks/zinc.json 7f71a774800111e50b42de0e6159ed2d2a807d32 data/forge/tags/items/storage_blocks/zinc.json
508730d3822c54d355329bf6a33d58071653afad data/minecraft/tags/blocks/beacon_base_blocks.json 508730d3822c54d355329bf6a33d58071653afad data/minecraft/tags/blocks/beacon_base_blocks.json
31424fe956db0354a9f24c61baf977a2961c8db6 data/minecraft/tags/blocks/impermeable.json 69f596fcb065e26b02ce246760432b5174191b76 data/minecraft/tags/blocks/impermeable.json
9dadc647e17b6262c13b6d8eda9139e30ce7e7d0 data/minecraft/tags/blocks/rails.json 9dadc647e17b6262c13b6d8eda9139e30ce7e7d0 data/minecraft/tags/blocks/rails.json
29e6f7e3d4be9a9b0af1fca5d32fa55e29905ce2 data/minecraft/tags/blocks/slabs.json 29e6f7e3d4be9a9b0af1fca5d32fa55e29905ce2 data/minecraft/tags/blocks/slabs.json
0d188ad2c33d10ee8f0d455c4e63a4460a8302fb data/minecraft/tags/blocks/stairs.json 0d188ad2c33d10ee8f0d455c4e63a4460a8302fb data/minecraft/tags/blocks/stairs.json

View file

@ -303,8 +303,8 @@
{ {
"when": { "when": {
"west": "false", "west": "false",
"down": "false",
"east": "true", "east": "true",
"down": "false",
"up": "true" "up": "true"
}, },
"apply": { "apply": {
@ -314,8 +314,8 @@
{ {
"when": { "when": {
"west": "true", "west": "true",
"down": "false",
"east": "false", "east": "false",
"down": "false",
"up": "true" "up": "true"
}, },
"apply": { "apply": {
@ -325,8 +325,8 @@
{ {
"when": { "when": {
"west": "false", "west": "false",
"down": "true",
"east": "true", "east": "true",
"down": "true",
"up": "false" "up": "false"
}, },
"apply": { "apply": {
@ -336,8 +336,8 @@
{ {
"when": { "when": {
"west": "true", "west": "true",
"down": "true",
"east": "false", "east": "false",
"down": "true",
"up": "false" "up": "false"
}, },
"apply": { "apply": {
@ -347,8 +347,8 @@
{ {
"when": { "when": {
"west": "false", "west": "false",
"down": "true",
"east": "false", "east": "false",
"down": "true",
"up": "true" "up": "true"
}, },
"apply": { "apply": {
@ -358,8 +358,8 @@
{ {
"when": { "when": {
"west": "false", "west": "false",
"down": "false",
"east": "false", "east": "false",
"down": "false",
"up": "true" "up": "true"
}, },
"apply": { "apply": {
@ -369,8 +369,8 @@
{ {
"when": { "when": {
"west": "false", "west": "false",
"down": "true",
"east": "false", "east": "false",
"down": "true",
"up": "false" "up": "false"
}, },
"apply": { "apply": {
@ -380,8 +380,8 @@
{ {
"when": { "when": {
"west": "true", "west": "true",
"down": "false",
"east": "true", "east": "true",
"down": "false",
"up": "false" "up": "false"
}, },
"apply": { "apply": {
@ -391,8 +391,8 @@
{ {
"when": { "when": {
"west": "false", "west": "false",
"down": "false",
"east": "true", "east": "true",
"down": "false",
"up": "false" "up": "false"
}, },
"apply": { "apply": {
@ -402,8 +402,8 @@
{ {
"when": { "when": {
"west": "true", "west": "true",
"down": "false",
"east": "false", "east": "false",
"down": "false",
"up": "false" "up": "false"
}, },
"apply": { "apply": {
@ -413,8 +413,8 @@
{ {
"when": { "when": {
"west": "false", "west": "false",
"down": "false",
"east": "false", "east": "false",
"down": "false",
"up": "false" "up": "false"
}, },
"apply": { "apply": {

View file

@ -0,0 +1,30 @@
{
"variants": {
"facing=down": {
"model": "create:block/portable_fluid_interface/block",
"x": 180
},
"facing=up": {
"model": "create:block/portable_fluid_interface/block"
},
"facing=north": {
"model": "create:block/portable_fluid_interface/block",
"x": 90
},
"facing=south": {
"model": "create:block/portable_fluid_interface/block",
"x": 90,
"y": 180
},
"facing=west": {
"model": "create:block/portable_fluid_interface/block",
"x": 90,
"y": 270
},
"facing=east": {
"model": "create:block/portable_fluid_interface/block",
"x": 90,
"y": 90
}
}
}

View file

@ -323,6 +323,7 @@
"block.create.polished_weathered_limestone_slab": "q\u0250\u05DFS \u01DDuo\u0287s\u01DD\u026F\u0131\uA780 p\u01DD\u0279\u01DD\u0265\u0287\u0250\u01DDM p\u01DD\u0265s\u0131\u05DFo\u0500", "block.create.polished_weathered_limestone_slab": "q\u0250\u05DFS \u01DDuo\u0287s\u01DD\u026F\u0131\uA780 p\u01DD\u0279\u01DD\u0265\u0287\u0250\u01DDM p\u01DD\u0265s\u0131\u05DFo\u0500",
"block.create.polished_weathered_limestone_stairs": "s\u0279\u0131\u0250\u0287S \u01DDuo\u0287s\u01DD\u026F\u0131\uA780 p\u01DD\u0279\u01DD\u0265\u0287\u0250\u01DDM p\u01DD\u0265s\u0131\u05DFo\u0500", "block.create.polished_weathered_limestone_stairs": "s\u0279\u0131\u0250\u0287S \u01DDuo\u0287s\u01DD\u026F\u0131\uA780 p\u01DD\u0279\u01DD\u0265\u0287\u0250\u01DDM p\u01DD\u0265s\u0131\u05DFo\u0500",
"block.create.polished_weathered_limestone_wall": "\u05DF\u05DF\u0250M \u01DDuo\u0287s\u01DD\u026F\u0131\uA780 p\u01DD\u0279\u01DD\u0265\u0287\u0250\u01DDM p\u01DD\u0265s\u0131\u05DFo\u0500", "block.create.polished_weathered_limestone_wall": "\u05DF\u05DF\u0250M \u01DDuo\u0287s\u01DD\u026F\u0131\uA780 p\u01DD\u0279\u01DD\u0265\u0287\u0250\u01DDM p\u01DD\u0265s\u0131\u05DFo\u0500",
"block.create.portable_fluid_interface": "\u01DD\u0254\u0250\u025F\u0279\u01DD\u0287uI p\u0131n\u05DF\u2132 \u01DD\u05DFq\u0250\u0287\u0279o\u0500",
"block.create.portable_storage_interface": "\u01DD\u0254\u0250\u025F\u0279\u01DD\u0287uI \u01DDb\u0250\u0279o\u0287S \u01DD\u05DFq\u0250\u0287\u0279o\u0500", "block.create.portable_storage_interface": "\u01DD\u0254\u0250\u025F\u0279\u01DD\u0287uI \u01DDb\u0250\u0279o\u0287S \u01DD\u05DFq\u0250\u0287\u0279o\u0500",
"block.create.powered_latch": "\u0265\u0254\u0287\u0250\uA780 p\u01DD\u0279\u01DD\u028Do\u0500", "block.create.powered_latch": "\u0265\u0254\u0287\u0250\uA780 p\u01DD\u0279\u01DD\u028Do\u0500",
"block.create.powered_toggle_latch": "\u0265\u0254\u0287\u0250\uA780 \u01DD\u05DFbbo\u27D8 p\u01DD\u0279\u01DD\u028Do\u0500", "block.create.powered_toggle_latch": "\u0265\u0254\u0287\u0250\uA780 \u01DD\u05DFbbo\u27D8 p\u01DD\u0279\u01DD\u028Do\u0500",

View file

@ -326,6 +326,7 @@
"block.create.polished_weathered_limestone_slab": "Polished Weathered Limestone Slab", "block.create.polished_weathered_limestone_slab": "Polished Weathered Limestone Slab",
"block.create.polished_weathered_limestone_stairs": "Polished Weathered Limestone Stairs", "block.create.polished_weathered_limestone_stairs": "Polished Weathered Limestone Stairs",
"block.create.polished_weathered_limestone_wall": "Polished Weathered Limestone Wall", "block.create.polished_weathered_limestone_wall": "Polished Weathered Limestone Wall",
"block.create.portable_fluid_interface": "Portable Fluid Interface",
"block.create.portable_storage_interface": "Portable Storage Interface", "block.create.portable_storage_interface": "Portable Storage Interface",
"block.create.powered_latch": "Powered Latch", "block.create.powered_latch": "Powered Latch",
"block.create.powered_toggle_latch": "Powered Toggle Latch", "block.create.powered_toggle_latch": "Powered Toggle Latch",

View file

@ -1,5 +1,5 @@
{ {
"_": "Missing Localizations: 1042", "_": "Missing Localizations: 1043",
"_": "->------------------------] Game Elements [------------------------<-", "_": "->------------------------] Game Elements [------------------------<-",
@ -327,6 +327,7 @@
"block.create.polished_weathered_limestone_slab": "Polierte Verwitterte Kalksteinstufe", "block.create.polished_weathered_limestone_slab": "Polierte Verwitterte Kalksteinstufe",
"block.create.polished_weathered_limestone_stairs": "UNLOCALIZED: Polished Weathered Limestone Stairs", "block.create.polished_weathered_limestone_stairs": "UNLOCALIZED: Polished Weathered Limestone Stairs",
"block.create.polished_weathered_limestone_wall": "UNLOCALIZED: Polished Weathered Limestone Wall", "block.create.polished_weathered_limestone_wall": "UNLOCALIZED: Polished Weathered Limestone Wall",
"block.create.portable_fluid_interface": "UNLOCALIZED: Portable Fluid Interface",
"block.create.portable_storage_interface": "UNLOCALIZED: Portable Storage Interface", "block.create.portable_storage_interface": "UNLOCALIZED: Portable Storage Interface",
"block.create.powered_latch": "UNLOCALIZED: Powered Latch", "block.create.powered_latch": "UNLOCALIZED: Powered Latch",
"block.create.powered_toggle_latch": "UNLOCALIZED: Powered Toggle Latch", "block.create.powered_toggle_latch": "UNLOCALIZED: Powered Toggle Latch",

View file

@ -1,5 +1,5 @@
{ {
"_": "Missing Localizations: 671", "_": "Missing Localizations: 672",
"_": "->------------------------] Game Elements [------------------------<-", "_": "->------------------------] Game Elements [------------------------<-",
@ -327,6 +327,7 @@
"block.create.polished_weathered_limestone_slab": "Dalle de calcaire patinées", "block.create.polished_weathered_limestone_slab": "Dalle de calcaire patinées",
"block.create.polished_weathered_limestone_stairs": "UNLOCALIZED: Polished Weathered Limestone Stairs", "block.create.polished_weathered_limestone_stairs": "UNLOCALIZED: Polished Weathered Limestone Stairs",
"block.create.polished_weathered_limestone_wall": "UNLOCALIZED: Polished Weathered Limestone Wall", "block.create.polished_weathered_limestone_wall": "UNLOCALIZED: Polished Weathered Limestone Wall",
"block.create.portable_fluid_interface": "UNLOCALIZED: Portable Fluid Interface",
"block.create.portable_storage_interface": "Interface de stockage portable", "block.create.portable_storage_interface": "Interface de stockage portable",
"block.create.powered_latch": "Verrou alimenté", "block.create.powered_latch": "Verrou alimenté",
"block.create.powered_toggle_latch": "Verrou alimenté à bascule", "block.create.powered_toggle_latch": "Verrou alimenté à bascule",

View file

@ -1,5 +1,5 @@
{ {
"_": "Missing Localizations: 655", "_": "Missing Localizations: 656",
"_": "->------------------------] Game Elements [------------------------<-", "_": "->------------------------] Game Elements [------------------------<-",
@ -327,6 +327,7 @@
"block.create.polished_weathered_limestone_slab": "Lastra di Calcare Consumato Levigato", "block.create.polished_weathered_limestone_slab": "Lastra di Calcare Consumato Levigato",
"block.create.polished_weathered_limestone_stairs": "UNLOCALIZED: Polished Weathered Limestone Stairs", "block.create.polished_weathered_limestone_stairs": "UNLOCALIZED: Polished Weathered Limestone Stairs",
"block.create.polished_weathered_limestone_wall": "UNLOCALIZED: Polished Weathered Limestone Wall", "block.create.polished_weathered_limestone_wall": "UNLOCALIZED: Polished Weathered Limestone Wall",
"block.create.portable_fluid_interface": "UNLOCALIZED: Portable Fluid Interface",
"block.create.portable_storage_interface": "Interfaccia di Archiviazione Portatile", "block.create.portable_storage_interface": "Interfaccia di Archiviazione Portatile",
"block.create.powered_latch": "Leva Alimentata", "block.create.powered_latch": "Leva Alimentata",
"block.create.powered_toggle_latch": "Leva Alimentata Alterata", "block.create.powered_toggle_latch": "Leva Alimentata Alterata",

View file

@ -1,5 +1,5 @@
{ {
"_": "Missing Localizations: 654", "_": "Missing Localizations: 655",
"_": "->------------------------] Game Elements [------------------------<-", "_": "->------------------------] Game Elements [------------------------<-",
@ -327,6 +327,7 @@
"block.create.polished_weathered_limestone_slab": "磨かれた風化石灰岩のハーフブロック", "block.create.polished_weathered_limestone_slab": "磨かれた風化石灰岩のハーフブロック",
"block.create.polished_weathered_limestone_stairs": "UNLOCALIZED: Polished Weathered Limestone Stairs", "block.create.polished_weathered_limestone_stairs": "UNLOCALIZED: Polished Weathered Limestone Stairs",
"block.create.polished_weathered_limestone_wall": "UNLOCALIZED: Polished Weathered Limestone Wall", "block.create.polished_weathered_limestone_wall": "UNLOCALIZED: Polished Weathered Limestone Wall",
"block.create.portable_fluid_interface": "UNLOCALIZED: Portable Fluid Interface",
"block.create.portable_storage_interface": "ポータブルストレージインターフェイス", "block.create.portable_storage_interface": "ポータブルストレージインターフェイス",
"block.create.powered_latch": "パワードラッチ", "block.create.powered_latch": "パワードラッチ",
"block.create.powered_toggle_latch": "パワードトグルラッチ", "block.create.powered_toggle_latch": "パワードトグルラッチ",

View file

@ -1,5 +1,5 @@
{ {
"_": "Missing Localizations: 655", "_": "Missing Localizations: 656",
"_": "->------------------------] Game Elements [------------------------<-", "_": "->------------------------] Game Elements [------------------------<-",
@ -327,6 +327,7 @@
"block.create.polished_weathered_limestone_slab": "윤나는 풍화된 석회암 반 블록", "block.create.polished_weathered_limestone_slab": "윤나는 풍화된 석회암 반 블록",
"block.create.polished_weathered_limestone_stairs": "UNLOCALIZED: Polished Weathered Limestone Stairs", "block.create.polished_weathered_limestone_stairs": "UNLOCALIZED: Polished Weathered Limestone Stairs",
"block.create.polished_weathered_limestone_wall": "UNLOCALIZED: Polished Weathered Limestone Wall", "block.create.polished_weathered_limestone_wall": "UNLOCALIZED: Polished Weathered Limestone Wall",
"block.create.portable_fluid_interface": "UNLOCALIZED: Portable Fluid Interface",
"block.create.portable_storage_interface": "이동식 저장소 인터페이스", "block.create.portable_storage_interface": "이동식 저장소 인터페이스",
"block.create.powered_latch": "레드스톤 걸쇠", "block.create.powered_latch": "레드스톤 걸쇠",
"block.create.powered_toggle_latch": "레드스톤 토글 걸쇠", "block.create.powered_toggle_latch": "레드스톤 토글 걸쇠",

View file

@ -1,5 +1,5 @@
{ {
"_": "Missing Localizations: 983", "_": "Missing Localizations: 984",
"_": "->------------------------] Game Elements [------------------------<-", "_": "->------------------------] Game Elements [------------------------<-",
@ -327,6 +327,7 @@
"block.create.polished_weathered_limestone_slab": "Gepolijste Verweerde Kalksteen Plaat", "block.create.polished_weathered_limestone_slab": "Gepolijste Verweerde Kalksteen Plaat",
"block.create.polished_weathered_limestone_stairs": "UNLOCALIZED: Polished Weathered Limestone Stairs", "block.create.polished_weathered_limestone_stairs": "UNLOCALIZED: Polished Weathered Limestone Stairs",
"block.create.polished_weathered_limestone_wall": "UNLOCALIZED: Polished Weathered Limestone Wall", "block.create.polished_weathered_limestone_wall": "UNLOCALIZED: Polished Weathered Limestone Wall",
"block.create.portable_fluid_interface": "UNLOCALIZED: Portable Fluid Interface",
"block.create.portable_storage_interface": "UNLOCALIZED: Portable Storage Interface", "block.create.portable_storage_interface": "UNLOCALIZED: Portable Storage Interface",
"block.create.powered_latch": "UNLOCALIZED: Powered Latch", "block.create.powered_latch": "UNLOCALIZED: Powered Latch",
"block.create.powered_toggle_latch": "UNLOCALIZED: Powered Toggle Latch", "block.create.powered_toggle_latch": "UNLOCALIZED: Powered Toggle Latch",

View file

@ -1,5 +1,5 @@
{ {
"_": "Missing Localizations: 1049", "_": "Missing Localizations: 1050",
"_": "->------------------------] Game Elements [------------------------<-", "_": "->------------------------] Game Elements [------------------------<-",
@ -327,6 +327,7 @@
"block.create.polished_weathered_limestone_slab": "Lajota de Calcário Polido Resistido", "block.create.polished_weathered_limestone_slab": "Lajota de Calcário Polido Resistido",
"block.create.polished_weathered_limestone_stairs": "UNLOCALIZED: Polished Weathered Limestone Stairs", "block.create.polished_weathered_limestone_stairs": "UNLOCALIZED: Polished Weathered Limestone Stairs",
"block.create.polished_weathered_limestone_wall": "UNLOCALIZED: Polished Weathered Limestone Wall", "block.create.polished_weathered_limestone_wall": "UNLOCALIZED: Polished Weathered Limestone Wall",
"block.create.portable_fluid_interface": "UNLOCALIZED: Portable Fluid Interface",
"block.create.portable_storage_interface": "UNLOCALIZED: Portable Storage Interface", "block.create.portable_storage_interface": "UNLOCALIZED: Portable Storage Interface",
"block.create.powered_latch": "UNLOCALIZED: Powered Latch", "block.create.powered_latch": "UNLOCALIZED: Powered Latch",
"block.create.powered_toggle_latch": "UNLOCALIZED: Powered Toggle Latch", "block.create.powered_toggle_latch": "UNLOCALIZED: Powered Toggle Latch",

View file

@ -1,5 +1,5 @@
{ {
"_": "Missing Localizations: 324", "_": "Missing Localizations: 325",
"_": "->------------------------] Game Elements [------------------------<-", "_": "->------------------------] Game Elements [------------------------<-",
@ -327,6 +327,7 @@
"block.create.polished_weathered_limestone_slab": "Плита из полированного выветренного известняка", "block.create.polished_weathered_limestone_slab": "Плита из полированного выветренного известняка",
"block.create.polished_weathered_limestone_stairs": "Ступени из полированного выветренного известняка", "block.create.polished_weathered_limestone_stairs": "Ступени из полированного выветренного известняка",
"block.create.polished_weathered_limestone_wall": "Стена из полированного выветренного известняка", "block.create.polished_weathered_limestone_wall": "Стена из полированного выветренного известняка",
"block.create.portable_fluid_interface": "UNLOCALIZED: Portable Fluid Interface",
"block.create.portable_storage_interface": "Портативный интерфейс хранения", "block.create.portable_storage_interface": "Портативный интерфейс хранения",
"block.create.powered_latch": "Механизированная защёлка", "block.create.powered_latch": "Механизированная защёлка",
"block.create.powered_toggle_latch": "Механизированная рычаг-защёлка", "block.create.powered_toggle_latch": "Механизированная рычаг-защёлка",

View file

@ -1,5 +1,5 @@
{ {
"_": "Missing Localizations: 337", "_": "Missing Localizations: 338",
"_": "->------------------------] Game Elements [------------------------<-", "_": "->------------------------] Game Elements [------------------------<-",
@ -327,6 +327,7 @@
"block.create.polished_weathered_limestone_slab": "磨制风化石灰岩台阶", "block.create.polished_weathered_limestone_slab": "磨制风化石灰岩台阶",
"block.create.polished_weathered_limestone_stairs": "磨制风化石灰岩楼梯", "block.create.polished_weathered_limestone_stairs": "磨制风化石灰岩楼梯",
"block.create.polished_weathered_limestone_wall": "磨制风化石灰岩墙", "block.create.polished_weathered_limestone_wall": "磨制风化石灰岩墙",
"block.create.portable_fluid_interface": "UNLOCALIZED: Portable Fluid Interface",
"block.create.portable_storage_interface": "移动式存储接口", "block.create.portable_storage_interface": "移动式存储接口",
"block.create.powered_latch": "锁存器", "block.create.powered_latch": "锁存器",
"block.create.powered_toggle_latch": "T触发器", "block.create.powered_toggle_latch": "T触发器",

View file

@ -1,6 +1,6 @@
{ {
"parent": "minecraft:block/cube_all", "parent": "minecraft:block/cube_all",
"textures": { "textures": {
"all": "create:block/brass_block" "all": "create:block/brass_storage_block"
} }
} }

View file

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

View file

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

View file

@ -0,0 +1,19 @@
{
"type": "minecraft:block",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "create:portable_fluid_interface"
}
],
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
]
}
]
}

View file

@ -0,0 +1,18 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
" B ",
" I "
],
"key": {
"I": {
"item": "create:copper_casing"
},
"B": {
"item": "create:andesite_funnel"
}
},
"result": {
"item": "create:portable_fluid_interface"
}
}

View file

@ -6,7 +6,7 @@
], ],
"key": { "key": {
"I": { "I": {
"item": "create:redstone_contact" "item": "create:brass_casing"
}, },
"B": { "B": {
"item": "create:andesite_funnel" "item": "create:andesite_funnel"

View file

@ -88,6 +88,10 @@ public class AllBlockPartials {
PORTABLE_STORAGE_INTERFACE_MIDDLE = get("portable_storage_interface/block_middle"), PORTABLE_STORAGE_INTERFACE_MIDDLE = get("portable_storage_interface/block_middle"),
PORTABLE_STORAGE_INTERFACE_MIDDLE_POWERED = get("portable_storage_interface/block_middle_powered"), PORTABLE_STORAGE_INTERFACE_MIDDLE_POWERED = get("portable_storage_interface/block_middle_powered"),
PORTABLE_STORAGE_INTERFACE_TOP = get("portable_storage_interface/block_top"), PORTABLE_STORAGE_INTERFACE_TOP = get("portable_storage_interface/block_top"),
PORTABLE_FLUID_INTERFACE_MIDDLE = get("portable_fluid_interface/block_middle"),
PORTABLE_FLUID_INTERFACE_MIDDLE_POWERED = get("portable_fluid_interface/block_middle_powered"),
PORTABLE_FLUID_INTERFACE_TOP = get("portable_fluid_interface/block_top"),
ARM_COG = get("mechanical_arm/cog"), ARM_BASE = get("mechanical_arm/base"), ARM_COG = get("mechanical_arm/cog"), ARM_BASE = get("mechanical_arm/base"),
ARM_LOWER_BODY = get("mechanical_arm/lower_body"), ARM_UPPER_BODY = get("mechanical_arm/upper_body"), ARM_LOWER_BODY = get("mechanical_arm/lower_body"), ARM_UPPER_BODY = get("mechanical_arm/upper_body"),

View file

@ -46,10 +46,10 @@ import com.simibubi.create.content.contraptions.components.motor.CreativeMotorGe
import com.simibubi.create.content.contraptions.components.press.MechanicalPressBlock; import com.simibubi.create.content.contraptions.components.press.MechanicalPressBlock;
import com.simibubi.create.content.contraptions.components.saw.SawBlock; import com.simibubi.create.content.contraptions.components.saw.SawBlock;
import com.simibubi.create.content.contraptions.components.saw.SawGenerator; import com.simibubi.create.content.contraptions.components.saw.SawGenerator;
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.StabilizedBearingMovementBehaviour;
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.ClockworkBearingBlock; import com.simibubi.create.content.contraptions.components.structureMovement.bearing.ClockworkBearingBlock;
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.MechanicalBearingBlock; import com.simibubi.create.content.contraptions.components.structureMovement.bearing.MechanicalBearingBlock;
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.SailBlock; import com.simibubi.create.content.contraptions.components.structureMovement.bearing.SailBlock;
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.StabilizedBearingMovementBehaviour;
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.WindmillBearingBlock; import com.simibubi.create.content.contraptions.components.structureMovement.bearing.WindmillBearingBlock;
import com.simibubi.create.content.contraptions.components.structureMovement.chassis.LinearChassisBlock; import com.simibubi.create.content.contraptions.components.structureMovement.chassis.LinearChassisBlock;
import com.simibubi.create.content.contraptions.components.structureMovement.chassis.LinearChassisBlock.ChassisCTBehaviour; import com.simibubi.create.content.contraptions.components.structureMovement.chassis.LinearChassisBlock.ChassisCTBehaviour;
@ -565,7 +565,7 @@ public class AllBlocks {
.register(); .register();
public static final BlockEntry<ValveHandleBlock>[] DYED_VALVE_HANDLES = new BlockEntry[DyeColor.values().length]; public static final BlockEntry<ValveHandleBlock>[] DYED_VALVE_HANDLES = new BlockEntry[DyeColor.values().length];
static { static {
for (DyeColor colour : DyeColor.values()) { for (DyeColor colour : DyeColor.values()) {
String colourName = colour.getString(); String colourName = colour.getString();
@ -632,6 +632,15 @@ public class AllBlocks {
.transform(customItemModel()) .transform(customItemModel())
.register(); .register();
public static final BlockEntry<PortableStorageInterfaceBlock> PORTABLE_FLUID_INTERFACE =
REGISTRATE.block("portable_fluid_interface", PortableStorageInterfaceBlock::forFluids)
.initialProperties(SharedProperties::softMetal)
.blockstate((c, p) -> p.directionalBlock(c.get(), AssetLookup.partialBaseModel(c, p)))
.onRegister(addMovementBehaviour(new PortableStorageInterfaceMovement()))
.item()
.transform(customItemModel())
.register();
// Contraptions // Contraptions
public static final BlockEntry<MechanicalPistonBlock> MECHANICAL_PISTON = public static final BlockEntry<MechanicalPistonBlock> MECHANICAL_PISTON =
@ -792,7 +801,7 @@ public class AllBlocks {
.register(); .register();
public static final BlockEntry<PortableStorageInterfaceBlock> PORTABLE_STORAGE_INTERFACE = public static final BlockEntry<PortableStorageInterfaceBlock> PORTABLE_STORAGE_INTERFACE =
REGISTRATE.block("portable_storage_interface", PortableStorageInterfaceBlock::new) REGISTRATE.block("portable_storage_interface", PortableStorageInterfaceBlock::forItems)
.initialProperties(SharedProperties::stone) .initialProperties(SharedProperties::stone)
.blockstate((c, p) -> p.directionalBlock(c.get(), AssetLookup.partialBaseModel(c, p))) .blockstate((c, p) -> p.directionalBlock(c.get(), AssetLookup.partialBaseModel(c, p)))
.onRegister(addMovementBehaviour(new PortableStorageInterfaceMovement())) .onRegister(addMovementBehaviour(new PortableStorageInterfaceMovement()))
@ -1204,6 +1213,8 @@ public class AllBlocks {
public static final BlockEntry<Block> BRASS_BLOCK = REGISTRATE.block("brass_block", p -> new Block(p)) public static final BlockEntry<Block> BRASS_BLOCK = REGISTRATE.block("brass_block", p -> new Block(p))
.initialProperties(() -> Blocks.IRON_BLOCK) .initialProperties(() -> Blocks.IRON_BLOCK)
.blockstate((c, p) -> p.simpleBlock(c.get(), p.models()
.cubeAll(c.getName(), p.modLoc("block/brass_storage_block"))))
.tag(Tags.Blocks.STORAGE_BLOCKS) .tag(Tags.Blocks.STORAGE_BLOCKS)
.tag(AllBlockTags.BEACON_BASE_BLOCKS.tag) .tag(AllBlockTags.BEACON_BASE_BLOCKS.tag)
.transform(tagBlockAndItem("storage_blocks/brass")) .transform(tagBlockAndItem("storage_blocks/brass"))

View file

@ -5,8 +5,9 @@ import com.simibubi.create.content.contraptions.components.actors.DrillRenderer;
import com.simibubi.create.content.contraptions.components.actors.DrillTileEntity; import com.simibubi.create.content.contraptions.components.actors.DrillTileEntity;
import com.simibubi.create.content.contraptions.components.actors.HarvesterRenderer; import com.simibubi.create.content.contraptions.components.actors.HarvesterRenderer;
import com.simibubi.create.content.contraptions.components.actors.HarvesterTileEntity; import com.simibubi.create.content.contraptions.components.actors.HarvesterTileEntity;
import com.simibubi.create.content.contraptions.components.actors.PortableFluidInterfaceTileEntity;
import com.simibubi.create.content.contraptions.components.actors.PortableItemInterfaceTileEntity;
import com.simibubi.create.content.contraptions.components.actors.PortableStorageInterfaceRenderer; import com.simibubi.create.content.contraptions.components.actors.PortableStorageInterfaceRenderer;
import com.simibubi.create.content.contraptions.components.actors.PortableStorageInterfaceTileEntity;
import com.simibubi.create.content.contraptions.components.clock.CuckooClockRenderer; import com.simibubi.create.content.contraptions.components.clock.CuckooClockRenderer;
import com.simibubi.create.content.contraptions.components.clock.CuckooClockTileEntity; import com.simibubi.create.content.contraptions.components.clock.CuckooClockTileEntity;
import com.simibubi.create.content.contraptions.components.crafter.MechanicalCrafterRenderer; import com.simibubi.create.content.contraptions.components.crafter.MechanicalCrafterRenderer;
@ -349,13 +350,19 @@ public class AllTileEntities {
.renderer(() -> HarvesterRenderer::new) .renderer(() -> HarvesterRenderer::new)
.register(); .register();
public static final TileEntityEntry<PortableStorageInterfaceTileEntity> PORTABLE_STORAGE_INTERFACE = public static final TileEntityEntry<PortableItemInterfaceTileEntity> PORTABLE_STORAGE_INTERFACE =
Create.registrate() Create.registrate()
.tileEntity("portable_storage_interface", PortableStorageInterfaceTileEntity::new) .tileEntity("portable_storage_interface", PortableItemInterfaceTileEntity::new)
.validBlocks(AllBlocks.PORTABLE_STORAGE_INTERFACE) .validBlocks(AllBlocks.PORTABLE_STORAGE_INTERFACE)
.renderer(() -> PortableStorageInterfaceRenderer::new) .renderer(() -> PortableStorageInterfaceRenderer::new)
.register(); .register();
public static final TileEntityEntry<PortableFluidInterfaceTileEntity> PORTABLE_FLUID_INTERFACE = Create.registrate()
.tileEntity("portable_fluid_interface", PortableFluidInterfaceTileEntity::new)
.validBlocks(AllBlocks.PORTABLE_FLUID_INTERFACE)
.renderer(() -> PortableStorageInterfaceRenderer::new)
.register();
public static final TileEntityEntry<FlywheelTileEntity> FLYWHEEL = Create.registrate() public static final TileEntityEntry<FlywheelTileEntity> FLYWHEEL = Create.registrate()
.tileEntity("flywheel", FlywheelTileEntity::new) .tileEntity("flywheel", FlywheelTileEntity::new)
.validBlocks(AllBlocks.FLYWHEEL) .validBlocks(AllBlocks.FLYWHEEL)

View file

@ -1,12 +1,5 @@
package com.simibubi.create.content.contraptions.base; package com.simibubi.create.content.contraptions.base;
import static net.minecraft.util.text.TextFormatting.GOLD;
import static net.minecraft.util.text.TextFormatting.GRAY;
import java.util.List;
import javax.annotation.Nullable;
import com.simibubi.create.Create; import com.simibubi.create.Create;
import com.simibubi.create.content.contraptions.KineticNetwork; import com.simibubi.create.content.contraptions.KineticNetwork;
import com.simibubi.create.content.contraptions.RotationPropagator; import com.simibubi.create.content.contraptions.RotationPropagator;
@ -20,7 +13,6 @@ import com.simibubi.create.foundation.item.TooltipHelper;
import com.simibubi.create.foundation.tileEntity.SmartTileEntity; import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.client.resources.I18n; import net.minecraft.client.resources.I18n;
@ -37,6 +29,12 @@ import net.minecraft.util.text.StringTextComponent;
import net.minecraft.util.text.TextFormatting; import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.World; import net.minecraft.world.World;
import javax.annotation.Nullable;
import java.util.List;
import static net.minecraft.util.text.TextFormatting.GOLD;
import static net.minecraft.util.text.TextFormatting.GRAY;
public abstract class KineticTileEntity extends SmartTileEntity public abstract class KineticTileEntity extends SmartTileEntity
implements ITickableTileEntity, IHaveGoggleInformation, IHaveHoveringInformation { implements ITickableTileEntity, IHaveGoggleInformation, IHaveHoveringInformation {
@ -354,13 +352,12 @@ public abstract class KineticTileEntity extends SmartTileEntity
return; return;
TileEntity tileEntityIn = world.getTileEntity(pos); TileEntity tileEntityIn = world.getTileEntity(pos);
BlockState currentState = world.getBlockState(pos);
boolean isKinetic = tileEntityIn instanceof KineticTileEntity; boolean isKinetic = tileEntityIn instanceof KineticTileEntity;
if (tileEntityIn == null) if (currentState == state)
return; return;
if (tileEntityIn.getBlockState() == state) if (tileEntityIn == null || !isKinetic) {
return;
if (!isKinetic) {
world.setBlockState(pos, state, 3); world.setBlockState(pos, state, 3);
return; return;
} }

View file

@ -0,0 +1,113 @@
package com.simibubi.create.content.contraptions.components.actors;
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.Direction;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.fluids.capability.templates.FluidTank;
public class PortableFluidInterfaceTileEntity extends PortableStorageInterfaceTileEntity {
protected LazyOptional<IFluidHandler> capability;
public PortableFluidInterfaceTileEntity(TileEntityType<?> tileEntityTypeIn) {
super(tileEntityTypeIn);
capability = createEmptyHandler();
}
@Override
public void startTransferringTo(Contraption contraption, float distance) {
LazyOptional<IFluidHandler> oldcap = capability;
capability = LazyOptional.of(() -> new InterfaceFluidHandler(contraption.fluidInventory));
oldcap.invalidate();
super.startTransferringTo(contraption, distance);
}
@Override
protected void invalidateCapability() {
capability.invalidate();
}
@Override
protected void stopTransferring() {
LazyOptional<IFluidHandler> oldcap = capability;
capability = createEmptyHandler();
oldcap.invalidate();
}
private LazyOptional<IFluidHandler> createEmptyHandler() {
return LazyOptional.of(() -> new InterfaceFluidHandler(new FluidTank(0)));
}
@Override
public <T> LazyOptional<T> getCapability(Capability<T> cap, Direction side) {
if (isFluidHandlerCap(cap))
return capability.cast();
return super.getCapability(cap, side);
}
class InterfaceFluidHandler implements IFluidHandler {
private IFluidHandler wrapped;
public InterfaceFluidHandler(IFluidHandler wrapped) {
this.wrapped = wrapped;
}
@Override
public int getTanks() {
return wrapped.getTanks();
}
@Override
public FluidStack getFluidInTank(int tank) {
return wrapped.getFluidInTank(tank);
}
@Override
public int getTankCapacity(int tank) {
return wrapped.getTankCapacity(tank);
}
@Override
public boolean isFluidValid(int tank, FluidStack stack) {
return wrapped.isFluidValid(tank, stack);
}
@Override
public int fill(FluidStack resource, FluidAction action) {
if (!isConnected())
return 0;
int fill = wrapped.fill(resource, action);
if (fill > 0 && action.execute())
onContentTransferred();
return fill;
}
@Override
public FluidStack drain(FluidStack resource, FluidAction action) {
if (!isConnected())
return FluidStack.EMPTY;
FluidStack drain = wrapped.drain(resource, action);
if (!drain.isEmpty() && action.execute())
onContentTransferred();
return drain;
}
@Override
public FluidStack drain(int maxDrain, FluidAction action) {
if (!isConnected())
return FluidStack.EMPTY;
FluidStack drain = wrapped.drain(maxDrain, action);
if (!drain.isEmpty() && (action.execute() || drain.getAmount() == 1))
onContentTransferred();
return drain;
}
}
}

View file

@ -0,0 +1,78 @@
package com.simibubi.create.content.contraptions.components.actors;
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
import com.simibubi.create.foundation.item.ItemHandlerWrapper;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.Direction;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.IItemHandlerModifiable;
import net.minecraftforge.items.ItemStackHandler;
public class PortableItemInterfaceTileEntity extends PortableStorageInterfaceTileEntity {
protected LazyOptional<IItemHandlerModifiable> capability;
public PortableItemInterfaceTileEntity(TileEntityType<?> tileEntityTypeIn) {
super(tileEntityTypeIn);
capability = LazyOptional.empty();
}
@Override
public void startTransferringTo(Contraption contraption, float distance) {
LazyOptional<IItemHandlerModifiable> oldCap = capability;
capability = LazyOptional.of(() -> new InterfaceItemHandler(contraption.inventory));
oldCap.invalidate();
super.startTransferringTo(contraption, distance);
}
@Override
protected void stopTransferring() {
LazyOptional<IItemHandlerModifiable> oldCap = capability;
capability = LazyOptional.of(() -> new InterfaceItemHandler(new ItemStackHandler(0)));
oldCap.invalidate();
}
@Override
protected void invalidateCapability() {
capability.invalidate();
}
@Override
public <T> LazyOptional<T> getCapability(Capability<T> cap, Direction side) {
if (isItemHandlerCap(cap))
return capability.cast();
return super.getCapability(cap, side);
}
class InterfaceItemHandler extends ItemHandlerWrapper {
public InterfaceItemHandler(IItemHandlerModifiable wrapped) {
super(wrapped);
}
@Override
public ItemStack extractItem(int slot, int amount, boolean simulate) {
if (!isConnected())
return ItemStack.EMPTY;
ItemStack extractItem = super.extractItem(slot, amount, simulate);
if (!simulate && !extractItem.isEmpty())
onContentTransferred();
return extractItem;
}
@Override
public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) {
if (!isConnected())
return stack;
ItemStack insertItem = super.insertItem(slot, stack, simulate);
if (!simulate && !insertItem.equals(stack, false))
onContentTransferred();
return insertItem;
}
}
}

View file

@ -8,6 +8,7 @@ import com.simibubi.create.foundation.block.ITE;
import com.simibubi.create.foundation.block.ProperDirectionalBlock; import com.simibubi.create.foundation.block.ProperDirectionalBlock;
import mcp.MethodsReturnNonnullByDefault; import mcp.MethodsReturnNonnullByDefault;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.item.BlockItemUseContext; import net.minecraft.item.BlockItemUseContext;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
@ -22,8 +23,19 @@ import net.minecraft.world.World;
public class PortableStorageInterfaceBlock extends ProperDirectionalBlock public class PortableStorageInterfaceBlock extends ProperDirectionalBlock
implements ITE<PortableStorageInterfaceTileEntity> { implements ITE<PortableStorageInterfaceTileEntity> {
public PortableStorageInterfaceBlock(Properties p_i48415_1_) { boolean fluids;
public static PortableStorageInterfaceBlock forItems(Properties p_i48415_1_) {
return new PortableStorageInterfaceBlock(p_i48415_1_, false);
}
public static PortableStorageInterfaceBlock forFluids(Properties p_i48415_1_) {
return new PortableStorageInterfaceBlock(p_i48415_1_, true);
}
private PortableStorageInterfaceBlock(Properties p_i48415_1_, boolean fluids) {
super(p_i48415_1_); super(p_i48415_1_);
this.fluids = fluids;
} }
@Override @Override
@ -33,7 +45,14 @@ public class PortableStorageInterfaceBlock extends ProperDirectionalBlock
@Override @Override
public TileEntity createTileEntity(BlockState state, IBlockReader world) { public TileEntity createTileEntity(BlockState state, IBlockReader world) {
return AllTileEntities.PORTABLE_STORAGE_INTERFACE.create(); return (fluids ? AllTileEntities.PORTABLE_FLUID_INTERFACE : AllTileEntities.PORTABLE_STORAGE_INTERFACE)
.create();
}
@Override
public void neighborChanged(BlockState state, World world, BlockPos pos, Block p_220069_4_, BlockPos p_220069_5_,
boolean p_220069_6_) {
withTileEntityDo(world, pos, PortableStorageInterfaceTileEntity::neighbourChanged);
} }
@Override @Override
@ -54,11 +73,8 @@ public class PortableStorageInterfaceBlock extends ProperDirectionalBlock
@Override @Override
public int getComparatorInputOverride(BlockState blockState, World worldIn, BlockPos pos) { public int getComparatorInputOverride(BlockState blockState, World worldIn, BlockPos pos) {
try { return getTileEntityOptional(worldIn, pos).map(te -> te.isConnected() ? 15 : 0)
return getTileEntity(worldIn, pos).isConnected() ? 15 : 0; .orElse(0);
} catch (TileEntityException e) {
}
return 0;
} }
@Override @Override

View file

@ -3,7 +3,6 @@ package com.simibubi.create.content.contraptions.components.actors;
import java.util.Optional; import java.util.Optional;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour; 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.MovementContext;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
@ -50,11 +49,12 @@ public class PortableStorageInterfaceMovement extends MovementBehaviour {
return false; return false;
Direction currentFacing = currentFacingIfValid.get(); Direction currentFacing = currentFacingIfValid.get();
PortableStorageInterfaceTileEntity psi = findStationaryInterface(context.world, pos, currentFacing); PortableStorageInterfaceTileEntity psi =
findStationaryInterface(context.world, pos, context.state, currentFacing);
if (psi == null) if (psi == null)
return false; return false;
if (psi.isTransferring() && !context.world.isRemote) if ((psi.isTransferring() || psi.isPowered()) && !context.world.isRemote)
return false; return false;
context.data.put(_workingPos_, NBTUtil.writeBlockPos(psi.getPos())); context.data.put(_workingPos_, NBTUtil.writeBlockPos(psi.getPos()));
if (!context.world.isRemote) { if (!context.world.isRemote) {
@ -94,7 +94,7 @@ public class PortableStorageInterfaceMovement extends MovementBehaviour {
return; return;
PortableStorageInterfaceTileEntity stationaryInterface = PortableStorageInterfaceTileEntity stationaryInterface =
getStationaryInterfaceAt(context.world, pos, currentFacingIfValid.get()); getStationaryInterfaceAt(context.world, pos, context.state, currentFacingIfValid.get());
if (stationaryInterface == null || !stationaryInterface.isTransferring()) { if (stationaryInterface == null || !stationaryInterface.isTransferring()) {
reset(context); reset(context);
return; return;
@ -112,10 +112,11 @@ public class PortableStorageInterfaceMovement extends MovementBehaviour {
context.stall = false; context.stall = false;
} }
private PortableStorageInterfaceTileEntity findStationaryInterface(World world, BlockPos pos, Direction facing) { private PortableStorageInterfaceTileEntity findStationaryInterface(World world, BlockPos pos, BlockState state,
Direction facing) {
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
PortableStorageInterfaceTileEntity interfaceAt = PortableStorageInterfaceTileEntity interfaceAt =
getStationaryInterfaceAt(world, pos.offset(facing, i), facing); getStationaryInterfaceAt(world, pos.offset(facing, i), state, facing);
if (interfaceAt == null) if (interfaceAt == null)
continue; continue;
return interfaceAt; return interfaceAt;
@ -123,12 +124,13 @@ public class PortableStorageInterfaceMovement extends MovementBehaviour {
return null; return null;
} }
private PortableStorageInterfaceTileEntity getStationaryInterfaceAt(World world, BlockPos pos, Direction facing) { private PortableStorageInterfaceTileEntity getStationaryInterfaceAt(World world, BlockPos pos, BlockState state,
Direction facing) {
TileEntity te = world.getTileEntity(pos); TileEntity te = world.getTileEntity(pos);
if (!(te instanceof PortableStorageInterfaceTileEntity)) if (!(te instanceof PortableStorageInterfaceTileEntity))
return null; return null;
BlockState blockState = world.getBlockState(pos); BlockState blockState = world.getBlockState(pos);
if (!AllBlocks.PORTABLE_STORAGE_INTERFACE.has(blockState)) if (blockState.getBlock() != state.getBlock())
return null; return null;
if (blockState.get(PortableStorageInterfaceBlock.FACING) != facing.getOpposite()) if (blockState.get(PortableStorageInterfaceBlock.FACING) != facing.getOpposite())
return null; return null;

View file

@ -5,6 +5,7 @@ import java.util.function.Consumer;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.vertex.IVertexBuilder; import com.mojang.blaze3d.vertex.IVertexBuilder;
import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllBlockPartials;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer;
import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AngleHelper;
@ -33,7 +34,8 @@ public class PortableStorageInterfaceRenderer extends SafeTileEntityRenderer<Por
BlockState blockState = te.getBlockState(); BlockState blockState = te.getBlockState();
float progress = te.getExtensionDistance(partialTicks); float progress = te.getExtensionDistance(partialTicks);
IVertexBuilder vb = buffer.getBuffer(RenderType.getSolid()); IVertexBuilder vb = buffer.getBuffer(RenderType.getSolid());
render(blockState, progress, te.isConnected(), sbb -> sbb.light(light).renderInto(ms, vb), ms); render(blockState, progress, te.isConnected(), sbb -> sbb.light(light)
.renderInto(ms, vb), ms);
} }
public static void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal, public static void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal,
@ -43,14 +45,14 @@ public class PortableStorageInterfaceRenderer extends SafeTileEntityRenderer<Por
IVertexBuilder vb = buffer.getBuffer(RenderType.getSolid()); IVertexBuilder vb = buffer.getBuffer(RenderType.getSolid());
float renderPartialTicks = Minecraft.getInstance() float renderPartialTicks = Minecraft.getInstance()
.getRenderPartialTicks(); .getRenderPartialTicks();
float progress = 0; float progress = 0;
boolean lit = false; boolean lit = false;
if (te != null) { if (te != null) {
progress = te.getExtensionDistance(renderPartialTicks); progress = te.getExtensionDistance(renderPartialTicks);
lit = te.isConnected(); lit = te.isConnected();
} }
render(blockState, progress, lit, sbb -> sbb.light(msLocal.peek() render(blockState, progress, lit, sbb -> sbb.light(msLocal.peek()
.getModel()) .getModel())
.renderInto(ms, vb), ms, msLocal); .renderInto(ms, vb), ms, msLocal);
@ -77,10 +79,8 @@ public class PortableStorageInterfaceRenderer extends SafeTileEntityRenderer<Por
for (MatrixStack ms : matrixStacks) for (MatrixStack ms : matrixStacks)
ms.push(); ms.push();
SuperByteBuffer middle = AllBlockPartials.PORTABLE_STORAGE_INTERFACE_MIDDLE.renderOn(blockState); SuperByteBuffer middle = getMiddleForState(blockState, lit).renderOn(blockState);
SuperByteBuffer top = AllBlockPartials.PORTABLE_STORAGE_INTERFACE_TOP.renderOn(blockState); SuperByteBuffer top = getTopForState(blockState).renderOn(blockState);
if (lit)
middle = AllBlockPartials.PORTABLE_STORAGE_INTERFACE_MIDDLE_POWERED.renderOn(blockState);
Direction facing = blockState.get(PortableStorageInterfaceBlock.FACING); Direction facing = blockState.get(PortableStorageInterfaceBlock.FACING);
for (MatrixStack ms : matrixStacks) for (MatrixStack ms : matrixStacks)
@ -109,4 +109,18 @@ public class PortableStorageInterfaceRenderer extends SafeTileEntityRenderer<Por
ms.pop(); ms.pop();
} }
static AllBlockPartials getMiddleForState(BlockState state, boolean lit) {
if (AllBlocks.PORTABLE_FLUID_INTERFACE.has(state))
return lit ? AllBlockPartials.PORTABLE_FLUID_INTERFACE_MIDDLE_POWERED
: AllBlockPartials.PORTABLE_FLUID_INTERFACE_MIDDLE;
return lit ? AllBlockPartials.PORTABLE_STORAGE_INTERFACE_MIDDLE_POWERED
: AllBlockPartials.PORTABLE_STORAGE_INTERFACE_MIDDLE;
}
static AllBlockPartials getTopForState(BlockState state) {
if (AllBlocks.PORTABLE_FLUID_INTERFACE.has(state))
return AllBlockPartials.PORTABLE_FLUID_INTERFACE_TOP;
return AllBlockPartials.PORTABLE_STORAGE_INTERFACE_TOP;
}
} }

View file

@ -4,61 +4,58 @@ import java.util.List;
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.item.ItemHandlerWrapper;
import com.simibubi.create.foundation.tileEntity.SmartTileEntity; import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
import com.simibubi.create.foundation.utility.LerpedFloat; import com.simibubi.create.foundation.utility.LerpedFloat;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tileentity.TileEntityType; import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.Direction;
import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.IItemHandlerModifiable;
public class PortableStorageInterfaceTileEntity extends SmartTileEntity { public abstract class PortableStorageInterfaceTileEntity extends SmartTileEntity {
protected int transferTimer; protected int transferTimer;
protected float distance; protected float distance;
protected LazyOptional<IItemHandlerModifiable> capability;
protected LerpedFloat connectionAnimation; protected LerpedFloat connectionAnimation;
protected boolean powered;
public PortableStorageInterfaceTileEntity(TileEntityType<?> tileEntityTypeIn) { public PortableStorageInterfaceTileEntity(TileEntityType<?> tileEntityTypeIn) {
super(tileEntityTypeIn); super(tileEntityTypeIn);
transferTimer = 0; transferTimer = 0;
capability = LazyOptional.empty(); connectionAnimation = LerpedFloat.linear()
connectionAnimation = LerpedFloat.linear().startWithValue(0); .startWithValue(0);
powered = false;
} }
public void startTransferringTo(Contraption contraption, float distance) { public void startTransferringTo(Contraption contraption, float distance) {
capability.invalidate();
capability = LazyOptional.of(() -> new InterfaceItemHandler(contraption.inventory));
this.distance = distance; this.distance = distance;
startConnecting(); startConnecting();
notifyUpdate(); notifyUpdate();
} }
protected abstract void stopTransferring();
protected abstract void invalidateCapability();
@Override @Override
public void tick() { public void tick() {
super.tick(); super.tick();
boolean wasConnected = isConnected(); boolean wasConnected = isConnected();
if (transferTimer > 0) { if (transferTimer > 0) {
transferTimer--; transferTimer--;
if (transferTimer == 0) if (transferTimer == 0 || powered)
capability.invalidate(); stopTransferring();
} }
boolean isConnected = isConnected(); boolean isConnected = isConnected();
if (wasConnected != isConnected && !world.isRemote) if (wasConnected != isConnected && !world.isRemote)
markDirty(); markDirty();
float progress = 0; float progress = 0;
int timeUnit = getTransferTimeout() / 2; int timeUnit = getTransferTimeout() / 2;
if (isConnected) if (isConnected)
@ -69,21 +66,41 @@ public class PortableStorageInterfaceTileEntity extends SmartTileEntity {
progress = MathHelper.lerp(transferTimer / (float) timeUnit, 0, 1); progress = MathHelper.lerp(transferTimer / (float) timeUnit, 0, 1);
connectionAnimation.setValue(progress); connectionAnimation.setValue(progress);
} }
@Override
public void remove() {
super.remove();
invalidateCapability();
}
@Override @Override
protected void fromTag(BlockState state, CompoundNBT compound, boolean clientPacket) { protected void fromTag(BlockState state, CompoundNBT compound, boolean clientPacket) {
super.fromTag(state, compound, clientPacket); super.fromTag(state, compound, clientPacket);
transferTimer = compound.getInt("Timer"); transferTimer = compound.getInt("Timer");
distance = compound.getFloat("Distance"); distance = compound.getFloat("Distance");
powered = compound.getBoolean("Powered");
} }
@Override @Override
protected void write(CompoundNBT compound, boolean clientPacket) { protected void write(CompoundNBT compound, boolean clientPacket) {
super.write(compound, clientPacket); super.write(compound, clientPacket);
compound.putInt("Timer", transferTimer); compound.putInt("Timer", transferTimer);
compound.putFloat("Distance", distance); compound.putFloat("Distance", distance);
compound.putBoolean("Powered", powered);
}
public void neighbourChanged() {
boolean isBlockPowered = world.isBlockPowered(pos);
if (isBlockPowered == powered)
return;
powered = isBlockPowered;
sendData();
} }
public boolean isPowered() {
return powered;
}
@Override @Override
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public AxisAlignedBB getRenderBoundingBox() { public AxisAlignedBB getRenderBoundingBox() {
@ -93,31 +110,24 @@ public class PortableStorageInterfaceTileEntity extends SmartTileEntity {
public boolean isTransferring() { public boolean isTransferring() {
return transferTimer != 0; return transferTimer != 0;
} }
boolean isConnected() { boolean isConnected() {
int timeUnit = getTransferTimeout() / 2; int timeUnit = getTransferTimeout() / 2;
return transferTimer >= timeUnit && transferTimer <= timeUnit * 3; return transferTimer >= timeUnit && transferTimer <= timeUnit * 3;
} }
float getExtensionDistance(float partialTicks) { float getExtensionDistance(float partialTicks) {
return connectionAnimation.getValue(partialTicks) * distance / 2; return connectionAnimation.getValue(partialTicks) * distance / 2;
} }
float getConnectionDistance() { float getConnectionDistance() {
return distance; return distance;
} }
@Override
public <T> LazyOptional<T> getCapability(Capability<T> cap, Direction side) {
if (isItemHandlerCap(cap))
return capability.cast();
return super.getCapability(cap, side);
}
public void startConnecting() { public void startConnecting() {
transferTimer = getTransferTimeout() * 2; transferTimer = getTransferTimeout() * 2;
} }
public void onContentTransferred() { public void onContentTransferred() {
int timeUnit = getTransferTimeout() / 2; int timeUnit = getTransferTimeout() / 2;
transferTimer = timeUnit * 3; transferTimer = timeUnit * 3;
@ -131,32 +141,4 @@ public class PortableStorageInterfaceTileEntity extends SmartTileEntity {
@Override @Override
public void addBehaviours(List<TileEntityBehaviour> behaviours) {} public void addBehaviours(List<TileEntityBehaviour> behaviours) {}
class InterfaceItemHandler extends ItemHandlerWrapper {
public InterfaceItemHandler(IItemHandlerModifiable wrapped) {
super(wrapped);
}
@Override
public ItemStack extractItem(int slot, int amount, boolean simulate) {
if (!isConnected())
return ItemStack.EMPTY;
ItemStack extractItem = super.extractItem(slot, amount, simulate);
if (!simulate && !extractItem.isEmpty())
onContentTransferred();
return extractItem;
}
@Override
public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) {
if (!isConnected())
return stack;
ItemStack insertItem = super.insertItem(slot, stack, simulate);
if (!simulate && !insertItem.equals(stack, false))
onContentTransferred();
return insertItem;
}
}
} }

View file

@ -2,9 +2,7 @@ package com.simibubi.create.content.contraptions.components.fan;
import com.simibubi.create.AllShapes; import com.simibubi.create.AllShapes;
import com.simibubi.create.AllTileEntities; import com.simibubi.create.AllTileEntities;
import com.simibubi.create.content.contraptions.wrench.IWrenchable;
import com.simibubi.create.foundation.block.ProperDirectionalBlock; import com.simibubi.create.foundation.block.ProperDirectionalBlock;
import mcp.MethodsReturnNonnullByDefault; import mcp.MethodsReturnNonnullByDefault;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
@ -24,7 +22,7 @@ import javax.annotation.ParametersAreNonnullByDefault;
@MethodsReturnNonnullByDefault @MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault @ParametersAreNonnullByDefault
public class NozzleBlock extends ProperDirectionalBlock implements IWrenchable { public class NozzleBlock extends ProperDirectionalBlock {
public NozzleBlock(Properties p_i48415_1_) { public NozzleBlock(Properties p_i48415_1_) {
super(p_i48415_1_); super(p_i48415_1_);

View file

@ -1,10 +1,13 @@
package com.simibubi.create.content.contraptions.components.structureMovement; package com.simibubi.create.content.contraptions.components.structureMovement;
import java.util.ArrayList; import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.UUID; import java.util.UUID;
import org.apache.commons.lang3.mutable.MutableInt;
import org.apache.commons.lang3.tuple.MutablePair; import org.apache.commons.lang3.tuple.MutablePair;
import com.simibubi.create.AllMovementBehaviours; import com.simibubi.create.AllMovementBehaviours;
@ -49,7 +52,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit
private static final DataParameter<Boolean> STALLED = private static final DataParameter<Boolean> STALLED =
EntityDataManager.createKey(AbstractContraptionEntity.class, DataSerializers.BOOLEAN); EntityDataManager.createKey(AbstractContraptionEntity.class, DataSerializers.BOOLEAN);
public final List<Entity> collidingEntities = new ArrayList<>(); public final Map<Entity, MutableInt> collidingEntities;
protected Contraption contraption; protected Contraption contraption;
protected boolean initialized; protected boolean initialized;
@ -58,6 +61,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit
public AbstractContraptionEntity(EntityType<?> entityTypeIn, World worldIn) { public AbstractContraptionEntity(EntityType<?> entityTypeIn, World worldIn) {
super(entityTypeIn, worldIn); super(entityTypeIn, worldIn);
prevPosInvalid = true; prevPosInvalid = true;
collidingEntities = new IdentityHashMap<>();
} }
protected void setContraption(Contraption contraption) { protected void setContraption(Contraption contraption) {
@ -205,6 +209,13 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit
return; return;
} }
for (Iterator<Entry<Entity, MutableInt>> iterator = collidingEntities.entrySet()
.iterator(); iterator.hasNext();)
if (iterator.next()
.getValue()
.incrementAndGet() > 3)
iterator.remove();
prevPosX = getX(); prevPosX = getX();
prevPosY = getY(); prevPosY = getY();
prevPosZ = getZ(); prevPosZ = getZ();
@ -212,6 +223,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit
if (!initialized) if (!initialized)
contraptionInitialize(); contraptionInitialize();
contraption.onEntityTick(world);
tickContraption(); tickContraption();
super.tick(); super.tick();
} }
@ -340,22 +352,6 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit
this.dataManager.register(STALLED, false); this.dataManager.register(STALLED, false);
} }
@Override
protected void readAdditional(CompoundNBT compound) {
initialized = compound.getBoolean("Initialized");
contraption = Contraption.fromNBT(world, compound.getCompound("Contraption"));
contraption.entity = this;
dataManager.set(STALLED, compound.getBoolean("Stalled"));
}
@Override
protected void writeAdditional(CompoundNBT compound) {
if (contraption != null)
compound.put("Contraption", contraption.writeNBT());
compound.putBoolean("Stalled", isStalled());
compound.putBoolean("Initialized", initialized);
}
@Override @Override
public IPacket<?> createSpawnPacket() { public IPacket<?> createSpawnPacket() {
return NetworkHooks.getEntitySpawningPacket(this); return NetworkHooks.getEntitySpawningPacket(this);
@ -364,13 +360,37 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit
@Override @Override
public void writeSpawnData(PacketBuffer buffer) { public void writeSpawnData(PacketBuffer buffer) {
CompoundNBT compound = new CompoundNBT(); CompoundNBT compound = new CompoundNBT();
writeAdditional(compound); writeAdditional(compound, true);
buffer.writeCompoundTag(compound); buffer.writeCompoundTag(compound);
} }
@Override
protected final void writeAdditional(CompoundNBT compound) {
writeAdditional(compound, false);
}
protected void writeAdditional(CompoundNBT compound, boolean spawnPacket) {
if (contraption != null)
compound.put("Contraption", contraption.writeNBT(spawnPacket));
compound.putBoolean("Stalled", isStalled());
compound.putBoolean("Initialized", initialized);
}
@Override @Override
public void readSpawnData(PacketBuffer additionalData) { public void readSpawnData(PacketBuffer additionalData) {
readAdditional(additionalData.readCompoundTag()); readAdditional(additionalData.readCompoundTag(), true);
}
@Override
protected final void readAdditional(CompoundNBT compound) {
readAdditional(compound, false);
}
protected void readAdditional(CompoundNBT compound, boolean spawnData) {
initialized = compound.getBoolean("Initialized");
contraption = Contraption.fromNBT(world, compound.getCompound("Contraption"), spawnData);
contraption.entity = this;
dataManager.set(STALLED, compound.getBoolean("Stalled"));
} }
public void disassemble() { public void disassemble() {
@ -378,8 +398,13 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit
return; return;
if (contraption == null) if (contraption == null)
return; return;
remove(); remove();
StructureTransform transform = makeStructureTransform(); StructureTransform transform = makeStructureTransform();
AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> this),
new ContraptionDisassemblyPacket(this.getEntityId(), transform));
contraption.addBlocksToWorld(world, transform); contraption.addBlocksToWorld(world, transform);
contraption.addPassengersToWorld(world, transform, getPassengers()); contraption.addPassengersToWorld(world, transform, getPassengers());
@ -396,14 +421,17 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit
} }
removePassengers(); removePassengers();
moveCollidedEntitiesOnDisassembly(transform);
}
for (Entity entity : collidingEntities) { private void moveCollidedEntitiesOnDisassembly(StructureTransform transform) {
Vector3d positionVec = getPositionVec(); for (Entity entity : collidingEntities.keySet()) {
Vector3d localVec = entity.getPositionVec() Vector3d localVec = toLocalVector(entity.getPositionVec(), 0);
.subtract(positionVec);
localVec = reverseRotation(localVec, 1);
Vector3d transformed = transform.apply(localVec); Vector3d transformed = transform.apply(localVec);
entity.setPositionAndUpdate(transformed.x, transformed.y, transformed.z); if (world.isRemote)
entity.setPosition(transformed.x, transformed.y + 1 / 16f, transformed.z);
else
entity.setPositionAndUpdate(transformed.x, transformed.y + 1 / 16f, transformed.z);
} }
} }
@ -449,6 +477,15 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit
ce.handleStallInformation(packet.x, packet.y, packet.z, packet.angle); ce.handleStallInformation(packet.x, packet.y, packet.z, packet.angle);
} }
@OnlyIn(Dist.CLIENT)
static void handleDisassemblyPacket(ContraptionDisassemblyPacket packet) {
Entity entity = Minecraft.getInstance().world.getEntityByID(packet.entityID);
if (!(entity instanceof AbstractContraptionEntity))
return;
AbstractContraptionEntity ce = (AbstractContraptionEntity) entity;
ce.moveCollidedEntitiesOnDisassembly(packet.transform);
}
protected abstract float getStalledAngle(); protected abstract float getStalledAngle();
protected abstract void handleStallInformation(float x, float y, float z, float angle); protected abstract void handleStallInformation(float x, float y, float z, float angle);

View file

@ -19,6 +19,8 @@ import com.simibubi.create.content.contraptions.components.structureMovement.pis
import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.PistonState; import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.PistonState;
import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyBlock; import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyBlock;
import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyTileEntity; import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyTileEntity;
import com.simibubi.create.content.contraptions.fluids.tank.FluidTankBlock;
import com.simibubi.create.content.contraptions.fluids.tank.FluidTankConnectivityHandler;
import com.simibubi.create.content.logistics.block.redstone.RedstoneLinkBlock; import com.simibubi.create.content.logistics.block.redstone.RedstoneLinkBlock;
import com.simibubi.create.foundation.utility.BlockHelper; import com.simibubi.create.foundation.utility.BlockHelper;
@ -46,6 +48,7 @@ import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.World; import net.minecraft.world.World;
public class BlockMovementTraits { public class BlockMovementTraits {
@ -56,9 +59,11 @@ public class BlockMovementTraits {
return true; return true;
if (state.getBlock() instanceof FenceGateBlock) if (state.getBlock() instanceof FenceGateBlock)
return true; return true;
if (state.getMaterial().isReplaceable()) if (state.getMaterial()
.isReplaceable())
return false; return false;
if (state.getCollisionShape(world, pos).isEmpty()) if (state.getCollisionShape(world, pos)
.isEmpty())
return false; return false;
return true; return true;
} }
@ -105,7 +110,7 @@ public class BlockMovementTraits {
Block block = state.getBlock(); Block block = state.getBlock();
if (BlockHelper.hasBlockStateProperty(state, BlockStateProperties.HANGING)) if (BlockHelper.hasBlockStateProperty(state, BlockStateProperties.HANGING))
return true; return true;
if (block instanceof LadderBlock) if (block instanceof LadderBlock)
return true; return true;
if (block instanceof TorchBlock) if (block instanceof TorchBlock)
@ -130,7 +135,8 @@ public class BlockMovementTraits {
/** /**
* Attached blocks will move if blocks they are attached to are moved * Attached blocks will move if blocks they are attached to are moved
*/ */
public static boolean isBlockAttachedTowards(BlockState state, Direction direction) { public static boolean isBlockAttachedTowards(IBlockReader world, BlockPos pos, BlockState state,
Direction direction) {
Block block = state.getBlock(); Block block = state.getBlock();
if (block instanceof LadderBlock) if (block instanceof LadderBlock)
return state.get(LadderBlock.FACING) == direction.getOpposite(); return state.get(LadderBlock.FACING) == direction.getOpposite();
@ -168,23 +174,30 @@ public class BlockMovementTraits {
if (block instanceof AbstractRailBlock) if (block instanceof AbstractRailBlock)
return direction == Direction.DOWN; return direction == Direction.DOWN;
if (block instanceof AttachedActorBlock) if (block instanceof AttachedActorBlock)
return direction == state.get(HarvesterBlock.HORIZONTAL_FACING).getOpposite(); return direction == state.get(HarvesterBlock.HORIZONTAL_FACING)
.getOpposite();
if (block instanceof HandCrankBlock) if (block instanceof HandCrankBlock)
return direction == state.get(HandCrankBlock.FACING).getOpposite(); return direction == state.get(HandCrankBlock.FACING)
.getOpposite();
if (block instanceof NozzleBlock) if (block instanceof NozzleBlock)
return direction == state.get(NozzleBlock.FACING).getOpposite(); return direction == state.get(NozzleBlock.FACING)
.getOpposite();
if (block instanceof EngineBlock) if (block instanceof EngineBlock)
return direction == state.get(EngineBlock.HORIZONTAL_FACING).getOpposite(); return direction == state.get(EngineBlock.HORIZONTAL_FACING)
.getOpposite();
if (block instanceof BellBlock) { if (block instanceof BellBlock) {
BellAttachment attachment = state.get(BlockStateProperties.BELL_ATTACHMENT); BellAttachment attachment = state.get(BlockStateProperties.BELL_ATTACHMENT);
if (attachment == BellAttachment.FLOOR) if (attachment == BellAttachment.FLOOR)
return direction == Direction.DOWN; return direction == Direction.DOWN;
if (attachment == BellAttachment.CEILING) if (attachment == BellAttachment.CEILING)
return direction == Direction.UP; return direction == Direction.UP;
return direction == state.get(HorizontalBlock.HORIZONTAL_FACING); return direction == state.get(HorizontalBlock.HORIZONTAL_FACING);
} }
if (state.getBlock() instanceof SailBlock) if (state.getBlock() instanceof SailBlock)
return direction.getAxis() != state.get(SailBlock.FACING).getAxis(); return direction.getAxis() != state.get(SailBlock.FACING)
.getAxis();
if (state.getBlock() instanceof FluidTankBlock)
return FluidTankConnectivityHandler.isConnected(world, pos, pos.offset(direction));
return false; return false;
} }
@ -210,8 +223,9 @@ public class BlockMovementTraits {
if (state.getBlock() instanceof CarpetBlock) if (state.getBlock() instanceof CarpetBlock)
return facing == Direction.UP; return facing == Direction.UP;
if (state.getBlock() instanceof SailBlock) if (state.getBlock() instanceof SailBlock)
return facing.getAxis() == state.get(SailBlock.FACING).getAxis(); return facing.getAxis() == state.get(SailBlock.FACING)
.getAxis();
return isBrittle(state); return isBrittle(state);
} }
} }

View file

@ -39,10 +39,12 @@ import com.simibubi.create.content.contraptions.components.structureMovement.pul
import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyBlock.MagnetBlock; import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyBlock.MagnetBlock;
import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyBlock.RopeBlock; import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyBlock.RopeBlock;
import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyTileEntity; import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyTileEntity;
import com.simibubi.create.content.contraptions.fluids.tank.FluidTankTileEntity;
import com.simibubi.create.content.contraptions.relays.belt.BeltBlock; import com.simibubi.create.content.contraptions.relays.belt.BeltBlock;
import com.simibubi.create.content.logistics.block.inventories.AdjustableCrateBlock; import com.simibubi.create.content.logistics.block.inventories.AdjustableCrateBlock;
import com.simibubi.create.content.logistics.block.redstone.RedstoneContactBlock; import com.simibubi.create.content.logistics.block.redstone.RedstoneContactBlock;
import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.fluid.CombinedTankWrapper;
import com.simibubi.create.foundation.utility.BlockFace; import com.simibubi.create.foundation.utility.BlockFace;
import com.simibubi.create.foundation.utility.BlockHelper; import com.simibubi.create.foundation.utility.BlockHelper;
import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Iterate;
@ -81,6 +83,10 @@ import net.minecraft.world.World;
import net.minecraft.world.gen.feature.template.Template.BlockInfo; import net.minecraft.world.gen.feature.template.Template.BlockInfo;
import net.minecraftforge.common.util.Constants.BlockFlags; import net.minecraftforge.common.util.Constants.BlockFlags;
import net.minecraftforge.common.util.Constants.NBT; import net.minecraftforge.common.util.Constants.NBT;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.IFluidTank;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.fluids.capability.templates.FluidTank;
import net.minecraftforge.items.IItemHandlerModifiable; import net.minecraftforge.items.IItemHandlerModifiable;
import net.minecraftforge.items.wrapper.CombinedInvWrapper; import net.minecraftforge.items.wrapper.CombinedInvWrapper;
@ -88,12 +94,14 @@ public abstract class Contraption {
public AbstractContraptionEntity entity; public AbstractContraptionEntity entity;
public CombinedInvWrapper inventory; public CombinedInvWrapper inventory;
public CombinedTankWrapper fluidInventory;
public AxisAlignedBB bounds; public AxisAlignedBB bounds;
public BlockPos anchor; public BlockPos anchor;
public boolean stalled; public boolean stalled;
protected Map<BlockPos, BlockInfo> blocks; protected Map<BlockPos, BlockInfo> blocks;
protected Map<BlockPos, MountedStorage> storage; protected Map<BlockPos, MountedStorage> storage;
protected Map<BlockPos, MountedFluidStorage> fluidStorage;
protected List<MutablePair<BlockInfo, MovementContext>> actors; protected List<MutablePair<BlockInfo, MovementContext>> actors;
protected Set<Pair<BlockPos, Direction>> superglue; protected Set<Pair<BlockPos, Direction>> superglue;
protected List<BlockPos> seats; protected List<BlockPos> seats;
@ -105,7 +113,7 @@ public abstract class Contraption {
private List<BlockFace> pendingSubContraptions; private List<BlockFace> pendingSubContraptions;
// Client // Client
public List<TileEntity> renderedTileEntities; public Map<BlockPos, TileEntity> renderedTileEntities;
public Contraption() { public Contraption() {
blocks = new HashMap<>(); blocks = new HashMap<>();
@ -114,9 +122,10 @@ public abstract class Contraption {
actors = new ArrayList<>(); actors = new ArrayList<>();
superglue = new HashSet<>(); superglue = new HashSet<>();
seatMapping = new HashMap<>(); seatMapping = new HashMap<>();
fluidStorage = new HashMap<>();
glueToRemove = new ArrayList<>(); glueToRemove = new ArrayList<>();
initialPassengers = new HashMap<>(); initialPassengers = new HashMap<>();
renderedTileEntities = new ArrayList<>(); renderedTileEntities = new HashMap<>();
pendingSubContraptions = new ArrayList<>(); pendingSubContraptions = new ArrayList<>();
stabilizedSubContraptions = new HashMap<>(); stabilizedSubContraptions = new HashMap<>();
} }
@ -140,10 +149,10 @@ public abstract class Contraption {
return true; return true;
} }
public static Contraption fromNBT(World world, CompoundNBT nbt) { public static Contraption fromNBT(World world, CompoundNBT nbt, boolean spawnData) {
String type = nbt.getString("Type"); String type = nbt.getString("Type");
Contraption contraption = AllContraptionTypes.fromType(type); Contraption contraption = AllContraptionTypes.fromType(type);
contraption.readNBT(world, nbt); contraption.readNBT(world, nbt, spawnData);
return contraption; return contraption;
} }
@ -195,6 +204,13 @@ public abstract class Contraption {
.map(MountedStorage::getItemHandler) .map(MountedStorage::getItemHandler)
.collect(Collectors.toList()); .collect(Collectors.toList());
inventory = new CombinedInvWrapper(Arrays.copyOf(list.toArray(), list.size(), IItemHandlerModifiable[].class)); inventory = new CombinedInvWrapper(Arrays.copyOf(list.toArray(), list.size(), IItemHandlerModifiable[].class));
List<IFluidHandler> fluidHandlers = fluidStorage.values()
.stream()
.map(MountedFluidStorage::getFluidHandler)
.collect(Collectors.toList());
fluidInventory = new CombinedTankWrapper(
Arrays.copyOf(fluidHandlers.toArray(), fluidHandlers.size(), IFluidHandler[].class));
} }
public void onEntityInitialize(World world, AbstractContraptionEntity contraptionEntity) { public void onEntityInitialize(World world, AbstractContraptionEntity contraptionEntity) {
@ -218,6 +234,10 @@ public abstract class Contraption {
} }
} }
public void onEntityTick(World world) {
fluidStorage.forEach((pos, mfs) -> mfs.tick(entity, pos, world.isRemote));
}
protected boolean moveBlock(World world, BlockPos pos, Direction forcedDirection, List<BlockPos> frontier, protected boolean moveBlock(World world, BlockPos pos, Direction forcedDirection, List<BlockPos> frontier,
Set<BlockPos> visited) { Set<BlockPos> visited) {
visited.add(pos); visited.add(pos);
@ -289,7 +309,7 @@ public abstract class Contraption {
boolean wasVisited = visited.contains(offsetPos); boolean wasVisited = visited.contains(offsetPos);
boolean faceHasGlue = superglue.containsKey(offset); boolean faceHasGlue = superglue.containsKey(offset);
boolean blockAttachedTowardsFace = boolean blockAttachedTowardsFace =
BlockMovementTraits.isBlockAttachedTowards(blockState, offset.getOpposite()); BlockMovementTraits.isBlockAttachedTowards(world, offsetPos, blockState, offset.getOpposite());
boolean brittle = BlockMovementTraits.isBrittle(blockState); boolean brittle = BlockMovementTraits.isBrittle(blockState);
if (!wasVisited && ((isSlimeBlock && !brittle) || blockAttachedTowardsFace || faceHasGlue)) if (!wasVisited && ((isSlimeBlock && !brittle) || blockAttachedTowardsFace || faceHasGlue))
@ -449,6 +469,8 @@ public abstract class Contraption {
TileEntity te = pair.getValue(); TileEntity te = pair.getValue();
if (te != null && MountedStorage.canUseAsStorage(te)) if (te != null && MountedStorage.canUseAsStorage(te))
storage.put(localPos, new MountedStorage(te)); storage.put(localPos, new MountedStorage(te));
if (te != null && MountedFluidStorage.canUseAsStorage(te))
fluidStorage.put(localPos, new MountedFluidStorage(te));
if (AllMovementBehaviours.contains(captured.state.getBlock())) if (AllMovementBehaviours.contains(captured.state.getBlock()))
actors.add(MutablePair.of(blockInfo, null)); actors.add(MutablePair.of(blockInfo, null));
} }
@ -462,6 +484,11 @@ public abstract class Contraption {
nbt.remove("x"); nbt.remove("x");
nbt.remove("y"); nbt.remove("y");
nbt.remove("z"); nbt.remove("z");
if (tileentity instanceof FluidTankTileEntity && nbt.contains("Controller"))
nbt.put("Controller",
NBTUtil.writeBlockPos(toLocalPos(NBTUtil.readBlockPos(nbt.getCompound("Controller")))));
return nbt; return nbt;
} }
@ -484,7 +511,7 @@ public abstract class Contraption {
return pos.equals(anchor); return pos.equals(anchor);
} }
public void readNBT(World world, CompoundNBT nbt) { public void readNBT(World world, CompoundNBT nbt, boolean spawnData) {
blocks.clear(); blocks.clear();
renderedTileEntities.clear(); renderedTileEntities.clear();
@ -523,7 +550,7 @@ public abstract class Contraption {
if (te instanceof KineticTileEntity) if (te instanceof KineticTileEntity)
((KineticTileEntity) te).setSpeed(0); ((KineticTileEntity) te).setSpeed(0);
te.getBlockState(); te.getBlockState();
renderedTileEntities.add(te); renderedTileEntities.put(info.pos, te);
} }
}); });
@ -555,6 +582,24 @@ public abstract class Contraption {
NBTHelper.iterateCompoundList(nbt.getList("Storage", NBT.TAG_COMPOUND), c -> storage NBTHelper.iterateCompoundList(nbt.getList("Storage", NBT.TAG_COMPOUND), c -> storage
.put(NBTUtil.readBlockPos(c.getCompound("Pos")), MountedStorage.deserialize(c.getCompound("Data")))); .put(NBTUtil.readBlockPos(c.getCompound("Pos")), MountedStorage.deserialize(c.getCompound("Data"))));
fluidStorage.clear();
NBTHelper.iterateCompoundList(nbt.getList("FluidStorage", NBT.TAG_COMPOUND), c -> fluidStorage
.put(NBTUtil.readBlockPos(c.getCompound("Pos")), MountedFluidStorage.deserialize(c.getCompound("Data"))));
if (spawnData)
fluidStorage.forEach((pos, mfs) -> {
TileEntity tileEntity = renderedTileEntities.get(pos);
if (!(tileEntity instanceof FluidTankTileEntity))
return;
FluidTankTileEntity tank = (FluidTankTileEntity) tileEntity;
IFluidTank tankInventory = tank.getTankInventory();
if (tankInventory instanceof FluidTank)
((FluidTank) tankInventory).setFluid(mfs.tank.getFluid());
tank.getFluidLevel()
.start(tank.getFillState());
mfs.assignTileEntity(tank);
});
IItemHandlerModifiable[] handlers = new IItemHandlerModifiable[storage.size()]; IItemHandlerModifiable[] handlers = new IItemHandlerModifiable[storage.size()];
int index = 0; int index = 0;
for (MountedStorage mountedStorage : storage.values()) for (MountedStorage mountedStorage : storage.values())
@ -568,7 +613,7 @@ public abstract class Contraption {
anchor = NBTUtil.readBlockPos(nbt.getCompound("Anchor")); anchor = NBTUtil.readBlockPos(nbt.getCompound("Anchor"));
} }
public CompoundNBT writeNBT() { public CompoundNBT writeNBT(boolean spawnPacket) {
CompoundNBT nbt = new CompoundNBT(); CompoundNBT nbt = new CompoundNBT();
nbt.putString("Type", getType().id); nbt.putString("Type", getType().id);
ListNBT blocksNBT = new ListNBT(); ListNBT blocksNBT = new ListNBT();
@ -601,14 +646,27 @@ public abstract class Contraption {
} }
ListNBT storageNBT = new ListNBT(); ListNBT storageNBT = new ListNBT();
for (BlockPos pos : storage.keySet()) { if (!spawnPacket) {
for (BlockPos pos : storage.keySet()) {
CompoundNBT c = new CompoundNBT();
MountedStorage mountedStorage = storage.get(pos);
if (!mountedStorage.isValid())
continue;
c.put("Pos", NBTUtil.writeBlockPos(pos));
c.put("Data", mountedStorage.serialize());
storageNBT.add(c);
}
}
ListNBT fluidStorageNBT = new ListNBT();
for (BlockPos pos : fluidStorage.keySet()) {
CompoundNBT c = new CompoundNBT(); CompoundNBT c = new CompoundNBT();
MountedStorage mountedStorage = storage.get(pos); MountedFluidStorage mountedStorage = fluidStorage.get(pos);
if (!mountedStorage.isValid()) if (!mountedStorage.isValid())
continue; continue;
c.put("Pos", NBTUtil.writeBlockPos(pos)); c.put("Pos", NBTUtil.writeBlockPos(pos));
c.put("Data", mountedStorage.serialize()); c.put("Data", mountedStorage.serialize());
storageNBT.add(c); fluidStorageNBT.add(c);
} }
nbt.put("Seats", NBTHelper.writeCompoundList(getSeats(), NBTUtil::writeBlockPos)); nbt.put("Seats", NBTHelper.writeCompoundList(getSeats(), NBTUtil::writeBlockPos));
@ -631,6 +689,7 @@ public abstract class Contraption {
nbt.put("Actors", actorsNBT); nbt.put("Actors", actorsNBT);
nbt.put("Superglue", superglueNBT); nbt.put("Superglue", superglueNBT);
nbt.put("Storage", storageNBT); nbt.put("Storage", storageNBT);
nbt.put("FluidStorage", fluidStorageNBT);
nbt.put("Anchor", NBTUtil.writeBlockPos(anchor)); nbt.put("Anchor", NBTUtil.writeBlockPos(anchor));
nbt.putBoolean("Stalled", stalled); nbt.putBoolean("Stalled", stalled);
@ -645,6 +704,8 @@ public abstract class Contraption {
public void removeBlocksFromWorld(World world, BlockPos offset) { public void removeBlocksFromWorld(World world, BlockPos offset) {
storage.values() storage.values()
.forEach(MountedStorage::removeStorageFromWorld); .forEach(MountedStorage::removeStorageFromWorld);
fluidStorage.values()
.forEach(MountedFluidStorage::removeStorageFromWorld);
glueToRemove.forEach(SuperGlueEntity::remove); glueToRemove.forEach(SuperGlueEntity::remove);
for (boolean brittles : Iterate.trueAndFalse) { for (boolean brittles : Iterate.trueAndFalse) {
@ -733,13 +794,22 @@ public abstract class Contraption {
tag.remove("InitialOffset"); tag.remove("InitialOffset");
} }
tileEntity.fromTag(tileEntity.getBlockState(), tag); if (tileEntity instanceof FluidTankTileEntity && tag.contains("LastKnownPos"))
tag.put("LastKnownPos", NBTUtil.writeBlockPos(BlockPos.ZERO.down()));
tileEntity.fromTag(block.state, tag);
if (storage.containsKey(block.pos)) { if (storage.containsKey(block.pos)) {
MountedStorage mountedStorage = storage.get(block.pos); MountedStorage mountedStorage = storage.get(block.pos);
if (mountedStorage.isValid()) if (mountedStorage.isValid())
mountedStorage.addStorageToWorld(tileEntity); mountedStorage.addStorageToWorld(tileEntity);
} }
if (fluidStorage.containsKey(block.pos)) {
MountedFluidStorage mountedStorage = fluidStorage.get(block.pos);
if (mountedStorage.isValid())
mountedStorage.addStorageToWorld(tileEntity);
}
} }
} }
} }
@ -858,4 +928,10 @@ public abstract class Contraption {
return actors; return actors;
} }
public void updateContainedFluid(BlockPos localPos, FluidStack containedFluid) {
MountedFluidStorage mountedFluidStorage = fluidStorage.get(localPos);
if (mountedFluidStorage != null)
mountedFluidStorage.updateFluid(containedFluid);
}
} }

View file

@ -8,6 +8,8 @@ import java.util.List;
import java.util.stream.Stream; import java.util.stream.Stream;
import org.apache.commons.lang3.mutable.MutableBoolean; import org.apache.commons.lang3.mutable.MutableBoolean;
import org.apache.commons.lang3.mutable.MutableFloat;
import org.apache.commons.lang3.mutable.MutableInt;
import org.apache.commons.lang3.mutable.MutableObject; import org.apache.commons.lang3.mutable.MutableObject;
import com.google.common.base.Predicates; import com.google.common.base.Predicates;
@ -64,8 +66,6 @@ public class ContraptionCollider {
if (bounds == null) if (bounds == null)
return; return;
contraptionEntity.collidingEntities.clear();
Vector3d contraptionPosition = contraptionEntity.getPositionVec(); Vector3d contraptionPosition = contraptionEntity.getPositionVec();
Vector3d contraptionMotion = contraptionPosition.subtract(contraptionEntity.getPrevPositionVec()); Vector3d contraptionMotion = contraptionPosition.subtract(contraptionEntity.getPrevPositionVec());
Vector3d anchorVec = contraptionEntity.getAnchorVec(); Vector3d anchorVec = contraptionEntity.getAnchorVec();
@ -122,13 +122,12 @@ public class ContraptionCollider {
// Prepare entity bounds // Prepare entity bounds
OrientedBB obb = new OrientedBB(localBB); OrientedBB obb = new OrientedBB(localBB);
obb.setRotation(rotationMatrix); obb.setRotation(rotationMatrix);
motion = rotationMatrix.transform(motion);
motion = motion.subtract(contraptionMotion); motion = motion.subtract(contraptionMotion);
motion = rotationMatrix.transform(motion);
MutableObject<Vector3d> collisionResponse = new MutableObject<>(Vector3d.ZERO); MutableObject<Vector3d> collisionResponse = new MutableObject<>(Vector3d.ZERO);
MutableObject<Vector3d> allowedMotion = new MutableObject<>(motion);
MutableBoolean futureCollision = new MutableBoolean(false);
MutableBoolean surfaceCollision = new MutableBoolean(false); MutableBoolean surfaceCollision = new MutableBoolean(false);
MutableFloat temporalResponse = new MutableFloat(1);
Vector3d obbCenter = obb.getCenter(); Vector3d obbCenter = obb.getCenter();
// Apply separation maths // Apply separation maths
@ -139,21 +138,22 @@ public class ContraptionCollider {
boolean doHorizontalPass = !rotation.hasVerticalRotation(); boolean doHorizontalPass = !rotation.hasVerticalRotation();
for (boolean horizontalPass : Iterate.trueAndFalse) { for (boolean horizontalPass : Iterate.trueAndFalse) {
boolean verticalPass = !horizontalPass || !doHorizontalPass;
for (AxisAlignedBB bb : bbs) { for (AxisAlignedBB bb : bbs) {
Vector3d currentResponse = collisionResponse.getValue(); Vector3d currentResponse = collisionResponse.getValue();
obb.setCenter(obbCenter.add(currentResponse)); obb.setCenter(obbCenter.add(currentResponse));
ContinuousSeparationManifold intersect = obb.intersect(bb, allowedMotion.getValue()); ContinuousSeparationManifold intersect = obb.intersect(bb, motion);
if (intersect == null) if (intersect == null)
continue; continue;
if ((!horizontalPass || !doHorizontalPass) && surfaceCollision.isFalse()) if (verticalPass && surfaceCollision.isFalse())
surfaceCollision.setValue(intersect.isSurfaceCollision()); surfaceCollision.setValue(intersect.isSurfaceCollision());
double timeOfImpact = intersect.getTimeOfImpact(); double timeOfImpact = intersect.getTimeOfImpact();
if (timeOfImpact > 0 && timeOfImpact < 1) { if (timeOfImpact > 0 && timeOfImpact < 1) {
futureCollision.setTrue(); if (temporalResponse.getValue() > timeOfImpact)
allowedMotion.setValue(intersect.getAllowedMotion(allowedMotion.getValue())); temporalResponse.setValue(timeOfImpact);
continue; continue;
} }
@ -162,28 +162,28 @@ public class ContraptionCollider {
collisionResponse.setValue(currentResponse.add(separation)); collisionResponse.setValue(currentResponse.add(separation));
} }
if (!horizontalPass || !doHorizontalPass) if (verticalPass)
break; break;
boolean noVerticalMotionResponse = allowedMotion.getValue().y == motion.y; boolean noVerticalMotionResponse = temporalResponse.getValue() == 1;
boolean noVerticalCollision = collisionResponse.getValue().y == 0; boolean noVerticalCollision = collisionResponse.getValue().y == 0;
if (noVerticalCollision && noVerticalMotionResponse) if (noVerticalCollision && noVerticalMotionResponse)
break; break;
// Re-run collisions with horizontal offset // Re-run collisions with horizontal offset
collisionResponse.setValue(collisionResponse.getValue() collisionResponse.setValue(collisionResponse.getValue()
.mul(1, 0, 1)); .mul(129 / 128f, 0, 129 / 128f));
allowedMotion.setValue(allowedMotion.getValue()
.mul(1, 0, 1)
.add(0, motion.y, 0));
continue; continue;
} }
// Resolve collision // Resolve collision
Vector3d entityMotion = entity.getMotion(); Vector3d entityMotion = entity.getMotion();
Vector3d totalResponse = collisionResponse.getValue(); Vector3d totalResponse = collisionResponse.getValue();
Vector3d motionResponse = allowedMotion.getValue();
boolean hardCollision = !totalResponse.equals(Vector3d.ZERO); boolean hardCollision = !totalResponse.equals(Vector3d.ZERO);
boolean temporalCollision = temporalResponse.getValue() != 1;
Vector3d motionResponse = !temporalCollision ? motion
: motion.normalize()
.scale(motion.length() * temporalResponse.getValue());
rotationMatrix.transpose(); rotationMatrix.transpose();
motionResponse = rotationMatrix.transform(motionResponse) motionResponse = rotationMatrix.transform(motionResponse)
@ -192,10 +192,11 @@ public class ContraptionCollider {
totalResponse = VecHelper.rotate(totalResponse, yawOffset, Axis.Y); totalResponse = VecHelper.rotate(totalResponse, yawOffset, Axis.Y);
rotationMatrix.transpose(); rotationMatrix.transpose();
if (futureCollision.isTrue() && playerType != PlayerType.SERVER) { if (temporalCollision && playerType != PlayerType.SERVER) {
if (motionResponse.y != entityMotion.y) { double idealVerticalMotion = motionResponse.y;
if (idealVerticalMotion != entityMotion.y) {
entity.setMotion(entityMotion.mul(1, 0, 1) entity.setMotion(entityMotion.mul(1, 0, 1)
.add(0, motionResponse.y, 0)); .add(0, idealVerticalMotion, 0));
entityMotion = entity.getMotion(); entityMotion = entity.getMotion();
} }
} }
@ -212,7 +213,8 @@ public class ContraptionCollider {
if (motionX != 0 && Math.abs(intersectX) > horizonalEpsilon && motionX > 0 == intersectX < 0) if (motionX != 0 && Math.abs(intersectX) > horizonalEpsilon && motionX > 0 == intersectX < 0)
entityMotion = entityMotion.mul(0, 1, 1); entityMotion = entityMotion.mul(0, 1, 1);
if (motionY != 0 && intersectY != 0 && motionY > 0 == intersectY < 0) if (motionY != 0 && intersectY != 0 && motionY > 0 == intersectY < 0)
entityMotion = entityMotion.mul(1, 0, 1); entityMotion = entityMotion.mul(1, 0, 1)
.add(0, contraptionMotion.y, 0);
if (motionZ != 0 && Math.abs(intersectZ) > horizonalEpsilon && motionZ > 0 == intersectZ < 0) if (motionZ != 0 && Math.abs(intersectZ) > horizonalEpsilon && motionZ > 0 == intersectZ < 0)
entityMotion = entityMotion.mul(1, 1, 0); entityMotion = entityMotion.mul(1, 1, 0);
} }
@ -226,25 +228,24 @@ public class ContraptionCollider {
} }
Vector3d allowedMovement = getAllowedMovement(totalResponse, entity); Vector3d allowedMovement = getAllowedMovement(totalResponse, entity);
contraptionEntity.collidingEntities.add(entity);
entity.velocityChanged = true;
entity.setPosition(entityPosition.x + allowedMovement.x, entityPosition.y + allowedMovement.y, entity.setPosition(entityPosition.x + allowedMovement.x, entityPosition.y + allowedMovement.y,
entityPosition.z + allowedMovement.z); entityPosition.z + allowedMovement.z);
entityPosition = entity.getPositionVec(); entityPosition = entity.getPositionVec();
entity.velocityChanged = true;
Vector3d contactPointMotion = Vector3d.ZERO; Vector3d contactPointMotion = Vector3d.ZERO;
if (surfaceCollision.isTrue()) { if (surfaceCollision.isTrue()) {
entity.fallDistance = 0; entity.fallDistance = 0;
entity.setOnGround(true); entity.setOnGround(true);
contraptionEntity.collidingEntities.add(entity); contraptionEntity.collidingEntities.put(entity, new MutableInt(0));
if (entity instanceof ItemEntity) if (entity instanceof ItemEntity)
entityMotion = entityMotion.mul(.5f, 1, .5f); entityMotion = entityMotion.mul(.5f, 1, .5f);
if (playerType != PlayerType.SERVER) { if (playerType != PlayerType.SERVER) {
contactPointMotion = contraptionEntity.getContactPointMotion(entityPosition); contactPointMotion = contraptionEntity.getContactPointMotion(entityPosition);
allowedMovement = getAllowedMovement(contactPointMotion, entity); allowedMovement = getAllowedMovement(contactPointMotion, entity);
entity.setPosition(entityPosition.x + allowedMovement.x, entityPosition.y + allowedMovement.y, entity.setPosition(entityPosition.x + allowedMovement.x,
entityPosition.z + allowedMovement.z); entityPosition.y, entityPosition.z + allowedMovement.z);
} }
} }
@ -258,7 +259,8 @@ public class ContraptionCollider {
float limbSwing = MathHelper.sqrt(d0 * d0 + d1 * d1) * 4.0F; float limbSwing = MathHelper.sqrt(d0 * d0 + d1 * d1) * 4.0F;
if (limbSwing > 1.0F) if (limbSwing > 1.0F)
limbSwing = 1.0F; limbSwing = 1.0F;
AllPackets.channel.sendToServer(new ClientMotionPacket(entityMotion, true, limbSwing)); AllPackets.channel
.sendToServer(new ClientMotionPacket(entityMotion, true, limbSwing));
} }
} }

View file

@ -0,0 +1,42 @@
package com.simibubi.create.content.contraptions.components.structureMovement;
import java.util.function.Supplier;
import com.simibubi.create.foundation.networking.SimplePacketBase;
import net.minecraft.network.PacketBuffer;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.network.NetworkEvent.Context;
public class ContraptionDisassemblyPacket extends SimplePacketBase {
int entityID;
StructureTransform transform;
public ContraptionDisassemblyPacket(int entityID, StructureTransform transform) {
this.entityID = entityID;
this.transform = transform;
}
public ContraptionDisassemblyPacket(PacketBuffer buffer) {
entityID = buffer.readInt();
transform = StructureTransform.fromBuffer(buffer);
}
@Override
public void write(PacketBuffer buffer) {
buffer.writeInt(entityID);
transform.writeToBuffer(buffer);
}
@Override
public void handle(Supplier<Context> context) {
context.get()
.enqueueWork(() -> DistExecutor.runWhenOn(Dist.CLIENT,
() -> () -> AbstractContraptionEntity.handleDisassemblyPacket(this)));
context.get()
.setPacketHandled(true);
}
}

View file

@ -71,7 +71,7 @@ public class ContraptionRenderer {
private static void renderTileEntities(World world, Contraption c, MatrixStack ms, MatrixStack msLocal, private static void renderTileEntities(World world, Contraption c, MatrixStack ms, MatrixStack msLocal,
IRenderTypeBuffer buffer) { IRenderTypeBuffer buffer) {
TileEntityRenderHelper.renderTileEntities(world, c.renderedTileEntities, ms, msLocal, buffer); TileEntityRenderHelper.renderTileEntities(world, c.renderedTileEntities.values(), ms, msLocal, buffer);
} }
private static SuperByteBuffer buildStructureBuffer(Contraption c, RenderType layer) { private static SuperByteBuffer buildStructureBuffer(Contraption c, RenderType layer) {
@ -86,10 +86,13 @@ public class ContraptionRenderer {
Random random = new Random(); Random random = new Random();
BufferBuilder builder = new BufferBuilder(DefaultVertexFormats.BLOCK.getIntegerSize()); BufferBuilder builder = new BufferBuilder(DefaultVertexFormats.BLOCK.getIntegerSize());
builder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK); builder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK);
renderWorld.setTileEntities(c.renderedTileEntities.values());
for (BlockInfo info : c.getBlocks().values()) for (BlockInfo info : c.getBlocks()
.values())
renderWorld.setBlockState(info.pos, info.state); renderWorld.setBlockState(info.pos, info.state);
for (BlockInfo info : c.getBlocks().values()) { for (BlockInfo info : c.getBlocks()
.values()) {
BlockState state = info.state; BlockState state = info.state;
if (state.getRenderType() == BlockRenderType.ENTITYBLOCK_ANIMATED) if (state.getRenderType() == BlockRenderType.ENTITYBLOCK_ANIMATED)

View file

@ -49,6 +49,13 @@ public class ControlledContraptionEntity extends AbstractContraptionEntity {
public boolean supportsTerrainCollision() { public boolean supportsTerrainCollision() {
return contraption instanceof TranslatingContraption; return contraption instanceof TranslatingContraption;
} }
@Override
public Vec3d getContactPointMotion(Vec3d globalContactPoint) {
if (contraption instanceof TranslatingContraption)
return getMotion();
return super.getContactPointMotion(globalContactPoint);
}
@Override @Override
protected void setContraption(Contraption contraption) { protected void setContraption(Contraption contraption) {
@ -60,8 +67,8 @@ public class ControlledContraptionEntity extends AbstractContraptionEntity {
} }
@Override @Override
protected void readAdditional(CompoundNBT compound) { protected void readAdditional(CompoundNBT compound, boolean spawnPacket) {
super.readAdditional(compound); super.readAdditional(compound, spawnPacket);
controllerPos = NBTUtil.readBlockPos(compound.getCompound("Controller")); controllerPos = NBTUtil.readBlockPos(compound.getCompound("Controller"));
if (compound.contains("Axis")) if (compound.contains("Axis"))
rotationAxis = NBTHelper.readEnum(compound, "Axis", Axis.class); rotationAxis = NBTHelper.readEnum(compound, "Axis", Axis.class);
@ -69,8 +76,8 @@ public class ControlledContraptionEntity extends AbstractContraptionEntity {
} }
@Override @Override
protected void writeAdditional(CompoundNBT compound) { protected void writeAdditional(CompoundNBT compound, boolean spawnPacket) {
super.writeAdditional(compound); super.writeAdditional(compound, spawnPacket);
compound.put("Controller", NBTUtil.writeBlockPos(controllerPos)); compound.put("Controller", NBTUtil.writeBlockPos(controllerPos));
if (rotationAxis != null) if (rotationAxis != null)
NBTHelper.writeEnum(compound, "Axis", rotationAxis); NBTHelper.writeEnum(compound, "Axis", rotationAxis);

View file

@ -1,5 +1,170 @@
package com.simibubi.create.content.contraptions.components.structureMovement; package com.simibubi.create.content.contraptions.components.structureMovement;
import com.simibubi.create.content.contraptions.components.structureMovement.sync.ContraptionFluidPacket;
import com.simibubi.create.content.contraptions.fluids.tank.CreativeFluidTankTileEntity;
import com.simibubi.create.content.contraptions.fluids.tank.CreativeFluidTankTileEntity.CreativeSmartFluidTank;
import com.simibubi.create.content.contraptions.fluids.tank.FluidTankTileEntity;
import com.simibubi.create.foundation.fluid.SmartFluidTank;
import com.simibubi.create.foundation.gui.widgets.InterpolatedChasingValue;
import com.simibubi.create.foundation.networking.AllPackets;
import com.simibubi.create.foundation.utility.NBTHelper;
import net.minecraft.entity.Entity;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.IFluidTank;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.fml.network.PacketDistributor;
public class MountedFluidStorage { public class MountedFluidStorage {
SmartFluidTank tank;
private boolean valid;
private TileEntity te;
private int packetCooldown = 0;
private boolean sendPacket = false;
public static boolean canUseAsStorage(TileEntity te) {
if (te instanceof FluidTankTileEntity)
return ((FluidTankTileEntity) te).isController();
return false;
}
public MountedFluidStorage(TileEntity te) {
assignTileEntity(te);
}
public void assignTileEntity(TileEntity te) {
this.te = te;
tank = createMountedTank(te);
}
private SmartFluidTank createMountedTank(TileEntity te) {
if (te instanceof CreativeFluidTankTileEntity)
return new CreativeSmartFluidTank(
((FluidTankTileEntity) te).getTotalTankSize() * FluidTankTileEntity.getCapacityMultiplier(), $ -> {
});
if (te instanceof FluidTankTileEntity)
return new SmartFluidTank(
((FluidTankTileEntity) te).getTotalTankSize() * FluidTankTileEntity.getCapacityMultiplier(),
this::onFluidStackChanged);
return null;
}
public void tick(Entity entity, BlockPos pos, boolean isRemote) {
if (!isRemote) {
if (packetCooldown > 0)
packetCooldown--;
else if (sendPacket) {
sendPacket = false;
AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> entity),
new ContraptionFluidPacket(entity.getEntityId(), pos, tank.getFluid()));
packetCooldown = 8;
}
return;
}
if (!(te instanceof FluidTankTileEntity))
return;
FluidTankTileEntity tank = (FluidTankTileEntity) te;
tank.getFluidLevel()
.tick();
}
public void updateFluid(FluidStack fluid) {
tank.setFluid(fluid);
if (!(te instanceof FluidTankTileEntity))
return;
float fillState = tank.getFluidAmount() / (float) tank.getCapacity();
FluidTankTileEntity tank = (FluidTankTileEntity) te;
if (tank.getFluidLevel() == null)
tank.setFluidLevel(new InterpolatedChasingValue().start(fillState));
tank.getFluidLevel()
.target(fillState);
IFluidTank tankInventory = tank.getTankInventory();
if (tankInventory instanceof SmartFluidTank)
((SmartFluidTank) tankInventory).setFluid(fluid);
}
public void removeStorageFromWorld() {
valid = false;
if (te == null)
return;
IFluidHandler teHandler = te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY)
.orElse(null);
if (!(teHandler instanceof SmartFluidTank))
return;
SmartFluidTank smartTank = (SmartFluidTank) teHandler;
tank.setFluid(smartTank.getFluid());
sendPacket = false;
valid = true;
}
private void onFluidStackChanged(FluidStack fs) {
sendPacket = true;
}
public void addStorageToWorld(TileEntity te) {
if (tank instanceof CreativeSmartFluidTank)
return;
LazyOptional<IFluidHandler> capability = te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY);
IFluidHandler teHandler = capability.orElse(null);
if (!(teHandler instanceof SmartFluidTank))
return;
SmartFluidTank inv = (SmartFluidTank) teHandler;
inv.setFluid(tank.getFluid());
}
public IFluidHandler getFluidHandler() {
return tank;
}
public CompoundNBT serialize() {
if (!valid)
return null;
CompoundNBT tag = tank.writeToNBT(new CompoundNBT());
tag.putInt("Capacity", tank.getCapacity());
if (tank instanceof CreativeSmartFluidTank) {
NBTHelper.putMarker(tag, "Bottomless");
tag.put("ProvidedStack", tank.getFluid()
.writeToNBT(new CompoundNBT()));
}
return tag;
}
public static MountedFluidStorage deserialize(CompoundNBT nbt) {
MountedFluidStorage storage = new MountedFluidStorage(null);
if (nbt == null)
return storage;
int capacity = nbt.getInt("Capacity");
storage.tank = new SmartFluidTank(capacity, storage::onFluidStackChanged);
storage.valid = true;
if (nbt.contains("Bottomless")) {
FluidStack providedStack = FluidStack.loadFluidStackFromNBT(nbt.getCompound("ProvidedStack"));
CreativeSmartFluidTank creativeSmartFluidTank = new CreativeSmartFluidTank(capacity, $ -> {
});
creativeSmartFluidTank.setContainedFluid(providedStack);
storage.tank = creativeSmartFluidTank;
return storage;
}
storage.tank.readFromNBT(nbt);
return storage;
}
public boolean isValid() {
return valid;
}
} }

View file

@ -31,7 +31,7 @@ public class MountedStorage {
public static boolean canUseAsStorage(TileEntity te) { public static boolean canUseAsStorage(TileEntity te) {
if (te == null) if (te == null)
return false; return false;
if (AllTileEntities.ADJUSTABLE_CRATE.is(te)) if (AllTileEntities.ADJUSTABLE_CRATE.is(te))
return true; return true;
if (AllTileEntities.CREATIVE_CRATE.is(te)) if (AllTileEntities.CREATIVE_CRATE.is(te))

View file

@ -146,8 +146,8 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity {
} }
@Override @Override
protected void readAdditional(CompoundNBT compound) { protected void readAdditional(CompoundNBT compound, boolean spawnPacket) {
super.readAdditional(compound); super.readAdditional(compound, spawnPacket);
if (compound.contains("InitialOrientation")) if (compound.contains("InitialOrientation"))
setInitialOrientation(NBTHelper.readEnum(compound, "InitialOrientation", Direction.class)); setInitialOrientation(NBTHelper.readEnum(compound, "InitialOrientation", Direction.class));
@ -170,8 +170,8 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity {
} }
@Override @Override
protected void writeAdditional(CompoundNBT compound) { protected void writeAdditional(CompoundNBT compound, boolean spawnPacket) {
super.writeAdditional(compound); super.writeAdditional(compound, spawnPacket);
if (motionBeforeStall != null) if (motionBeforeStall != null)
compound.put("CachedMotion", compound.put("CachedMotion",

View file

@ -20,6 +20,7 @@ import net.minecraft.block.BlockState;
import net.minecraft.block.HorizontalFaceBlock; import net.minecraft.block.HorizontalFaceBlock;
import net.minecraft.block.SlabBlock; import net.minecraft.block.SlabBlock;
import net.minecraft.block.StairsBlock; import net.minecraft.block.StairsBlock;
import net.minecraft.network.PacketBuffer;
import net.minecraft.state.BooleanProperty; import net.minecraft.state.BooleanProperty;
import net.minecraft.state.properties.AttachFace; import net.minecraft.state.properties.AttachFace;
import net.minecraft.state.properties.BellAttachment; import net.minecraft.state.properties.BellAttachment;
@ -41,6 +42,13 @@ public class StructureTransform {
Axis rotationAxis; Axis rotationAxis;
BlockPos offset; BlockPos offset;
private StructureTransform(BlockPos offset, int angle, Axis axis, Rotation rotation) {
this.offset = offset;
this.angle = angle;
rotationAxis = axis;
this.rotation = rotation;
}
public StructureTransform(BlockPos offset, float xRotation, float yRotation, float zRotation) { public StructureTransform(BlockPos offset, float xRotation, float yRotation, float zRotation) {
this.offset = offset; this.offset = offset;
if (xRotation != 0) { if (xRotation != 0) {
@ -72,14 +80,16 @@ public class StructureTransform {
public Vector3d apply(Vector3d localVec) { public Vector3d apply(Vector3d localVec) {
Vector3d vec = localVec; Vector3d vec = localVec;
vec = VecHelper.rotateCentered(vec, angle, rotationAxis); if (rotationAxis != null)
vec = VecHelper.rotateCentered(vec, angle, rotationAxis);
vec = vec.add(Vector3d.of(offset)); vec = vec.add(Vector3d.of(offset));
return vec; return vec;
} }
public BlockPos apply(BlockPos localPos) { public BlockPos apply(BlockPos localPos) {
Vector3d vec = VecHelper.getCenterOf(localPos); Vector3d vec = VecHelper.getCenterOf(localPos);
vec = VecHelper.rotateCentered(vec, angle, rotationAxis); if (rotationAxis != null)
vec = VecHelper.rotateCentered(vec, angle, rotationAxis);
localPos = new BlockPos(vec); localPos = new BlockPos(vec);
return localPos.add(offset); return localPos.add(offset);
} }
@ -203,8 +213,9 @@ public class StructureTransform {
protected BlockState transformBelt(BlockState state, boolean halfTurn) { protected BlockState transformBelt(BlockState state, boolean halfTurn) {
Direction initialDirection = state.get(BeltBlock.HORIZONTAL_FACING); Direction initialDirection = state.get(BeltBlock.HORIZONTAL_FACING);
boolean diagonal = state.get(BeltBlock.SLOPE) == BeltSlope.DOWNWARD || state.get(BeltBlock.SLOPE) == BeltSlope.UPWARD; boolean diagonal =
state.get(BeltBlock.SLOPE) == BeltSlope.DOWNWARD || state.get(BeltBlock.SLOPE) == BeltSlope.UPWARD;
if (!diagonal) { if (!diagonal) {
for (int i = 0; i < rotation.ordinal(); i++) { for (int i = 0; i < rotation.ordinal(); i++) {
Direction direction = state.get(BeltBlock.HORIZONTAL_FACING); Direction direction = state.get(BeltBlock.HORIZONTAL_FACING);
@ -212,7 +223,7 @@ public class StructureTransform {
boolean vertical = slope == BeltSlope.VERTICAL; boolean vertical = slope == BeltSlope.VERTICAL;
boolean horizontal = slope == BeltSlope.HORIZONTAL; boolean horizontal = slope == BeltSlope.HORIZONTAL;
boolean sideways = slope == BeltSlope.SIDEWAYS; boolean sideways = slope == BeltSlope.SIDEWAYS;
Direction newDirection = direction.getOpposite(); Direction newDirection = direction.getOpposite();
BeltSlope newSlope = BeltSlope.VERTICAL; BeltSlope newSlope = BeltSlope.VERTICAL;
@ -230,15 +241,15 @@ public class StructureTransform {
if (sideways) { if (sideways) {
newDirection = direction; newDirection = direction;
if (direction.getAxis() == rotationAxis) if (direction.getAxis() == rotationAxis)
newSlope = BeltSlope.HORIZONTAL; newSlope = BeltSlope.HORIZONTAL;
else else
newDirection = direction.rotateYCCW(); newDirection = direction.rotateYCCW();
} }
if (horizontal) { if (horizontal) {
newDirection = direction; newDirection = direction;
if (direction.getAxis() == rotationAxis) if (direction.getAxis() == rotationAxis)
newSlope = BeltSlope.SIDEWAYS; newSlope = BeltSlope.SIDEWAYS;
} }
@ -255,8 +266,7 @@ public class StructureTransform {
boolean downward = slope == BeltSlope.DOWNWARD; boolean downward = slope == BeltSlope.DOWNWARD;
// Rotate diagonal // Rotate diagonal
if (direction.getAxisDirection() == AxisDirection.POSITIVE ^ downward if (direction.getAxisDirection() == AxisDirection.POSITIVE ^ downward ^ direction.getAxis() == Axis.Z) {
^ direction.getAxis() == Axis.Z) {
state = state.with(BeltBlock.SLOPE, upward ? BeltSlope.DOWNWARD : BeltSlope.UPWARD); state = state.with(BeltBlock.SLOPE, upward ? BeltSlope.DOWNWARD : BeltSlope.UPWARD);
} else { } else {
state = state.with(BeltBlock.HORIZONTAL_FACING, newDirection); state = state.with(BeltBlock.HORIZONTAL_FACING, newDirection);
@ -268,10 +278,10 @@ public class StructureTransform {
Direction newDirection = direction.getOpposite(); Direction newDirection = direction.getOpposite();
BeltSlope slope = state.get(BeltBlock.SLOPE); BeltSlope slope = state.get(BeltBlock.SLOPE);
boolean vertical = slope == BeltSlope.VERTICAL; boolean vertical = slope == BeltSlope.VERTICAL;
if (diagonal) { if (diagonal) {
state = state.with(BeltBlock.SLOPE, state = state.with(BeltBlock.SLOPE, slope == BeltSlope.UPWARD ? BeltSlope.DOWNWARD
slope == BeltSlope.UPWARD ? BeltSlope.DOWNWARD : slope == BeltSlope.DOWNWARD ? BeltSlope.UPWARD : slope); : slope == BeltSlope.DOWNWARD ? BeltSlope.UPWARD : slope);
} else if (vertical) { } else if (vertical) {
state = state.with(BeltBlock.HORIZONTAL_FACING, newDirection); state = state.with(BeltBlock.HORIZONTAL_FACING, newDirection);
} }
@ -318,4 +328,21 @@ public class StructureTransform {
return rotated; return rotated;
} }
public static StructureTransform fromBuffer(PacketBuffer buffer) {
BlockPos readBlockPos = buffer.readBlockPos();
int readAngle = buffer.readInt();
int axisIndex = buffer.readVarInt();
int rotationIndex = buffer.readVarInt();
return new StructureTransform(readBlockPos, readAngle,
axisIndex == -1 ? null : Axis.values()[axisIndex],
rotationIndex == -1 ? null : Rotation.values()[rotationIndex]);
}
public void writeToBuffer(PacketBuffer buffer) {
buffer.writeBlockPos(offset);
buffer.writeInt(angle);
buffer.writeVarInt(rotationAxis == null ? -1 : rotationAxis.ordinal());
buffer.writeVarInt(rotation == null ? -1 : rotation.ordinal());
}
} }

View file

@ -62,18 +62,18 @@ public class BearingContraption extends Contraption {
} }
@Override @Override
public CompoundNBT writeNBT() { public CompoundNBT writeNBT(boolean spawnPacket) {
CompoundNBT tag = super.writeNBT(); CompoundNBT tag = super.writeNBT(spawnPacket);
tag.putInt("Sails", sailBlocks); tag.putInt("Sails", sailBlocks);
tag.putInt("Facing", facing.getIndex()); tag.putInt("Facing", facing.getIndex());
return tag; return tag;
} }
@Override @Override
public void readNBT(World world, CompoundNBT tag) { public void readNBT(World world, CompoundNBT tag, boolean spawnData) {
sailBlocks = tag.getInt("Sails"); sailBlocks = tag.getInt("Sails");
facing = Direction.byIndex(tag.getInt("Facing")); facing = Direction.byIndex(tag.getInt("Facing"));
super.readNBT(world, tag); super.readNBT(world, tag, spawnData);
} }
public int getSailBlocks() { public int getSailBlocks() {

View file

@ -100,8 +100,8 @@ public class ClockworkContraption extends Contraption {
} }
@Override @Override
public CompoundNBT writeNBT() { public CompoundNBT writeNBT(boolean spawnPacket) {
CompoundNBT tag = super.writeNBT(); CompoundNBT tag = super.writeNBT(spawnPacket);
tag.putInt("facing", facing.getIndex()); tag.putInt("facing", facing.getIndex());
tag.putInt("offset", offset); tag.putInt("offset", offset);
NBTHelper.writeEnum(tag, "HandType", handType); NBTHelper.writeEnum(tag, "HandType", handType);
@ -109,11 +109,11 @@ public class ClockworkContraption extends Contraption {
} }
@Override @Override
public void readNBT(World world, CompoundNBT tag) { public void readNBT(World world, CompoundNBT tag, boolean spawnData) {
facing = Direction.byIndex(tag.getInt("Facing")); facing = Direction.byIndex(tag.getInt("Facing"));
handType = NBTHelper.readEnum(tag, "HandType", HandType.class); handType = NBTHelper.readEnum(tag, "HandType", HandType.class);
offset = tag.getInt("offset"); offset = tag.getInt("offset");
super.readNBT(world, tag); super.readNBT(world, tag, spawnData);
} }
@Override @Override

View file

@ -42,16 +42,16 @@ public class StabilizedContraption extends Contraption {
} }
@Override @Override
public CompoundNBT writeNBT() { public CompoundNBT writeNBT(boolean spawnPacket) {
CompoundNBT tag = super.writeNBT(); CompoundNBT tag = super.writeNBT(spawnPacket);
tag.putInt("Facing", facing.getIndex()); tag.putInt("Facing", facing.getIndex());
return tag; return tag;
} }
@Override @Override
public void readNBT(World world, CompoundNBT tag) { public void readNBT(World world, CompoundNBT tag, boolean spawnData) {
facing = Direction.byIndex(tag.getInt("Facing")); facing = Direction.byIndex(tag.getInt("Facing"));
super.readNBT(world, tag); super.readNBT(world, tag, spawnData);
} }
@Override @Override

View file

@ -177,7 +177,7 @@ public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnDat
public static boolean isValidFace(World world, BlockPos pos, Direction direction) { public static boolean isValidFace(World world, BlockPos pos, Direction direction) {
BlockState state = world.getBlockState(pos); BlockState state = world.getBlockState(pos);
if (BlockMovementTraits.isBlockAttachedTowards(state, direction)) if (BlockMovementTraits.isBlockAttachedTowards(world, pos, state, direction))
return true; return true;
if (!BlockMovementTraits.movementNecessary(world, pos)) if (!BlockMovementTraits.movementNecessary(world, pos))
return false; return false;

View file

@ -167,7 +167,7 @@ public class MinecartContraptionItem extends Item {
intialOrientation = intialOrientation =
Optional.of(NBTHelper.readEnum(contraptionTag, "InitialOrientation", Direction.class)); Optional.of(NBTHelper.readEnum(contraptionTag, "InitialOrientation", Direction.class));
Contraption mountedContraption = Contraption.fromNBT(world, contraptionTag); Contraption mountedContraption = Contraption.fromNBT(world, contraptionTag, false);
OrientedContraptionEntity contraptionEntity = OrientedContraptionEntity contraptionEntity =
OrientedContraptionEntity.create(world, mountedContraption, intialOrientation); OrientedContraptionEntity.create(world, mountedContraption, intialOrientation);
@ -220,7 +220,7 @@ public class MinecartContraptionItem extends Item {
public static ItemStack create(Type type, OrientedContraptionEntity entity) { public static ItemStack create(Type type, OrientedContraptionEntity entity) {
ItemStack stack = ItemStack.EMPTY; ItemStack stack = ItemStack.EMPTY;
switch (type) { switch (type) {
case RIDEABLE: case RIDEABLE:
stack = AllItems.MINECART_CONTRAPTION.asStack(); stack = AllItems.MINECART_CONTRAPTION.asStack();
@ -234,12 +234,12 @@ public class MinecartContraptionItem extends Item {
default: default:
break; break;
} }
if (stack.isEmpty()) if (stack.isEmpty())
return stack; return stack;
CompoundNBT tag = entity.getContraption() CompoundNBT tag = entity.getContraption()
.writeNBT(); .writeNBT(false);
tag.remove("UUID"); tag.remove("UUID");
tag.remove("Pos"); tag.remove("Pos");
tag.remove("Motion"); tag.remove("Motion");

View file

@ -127,16 +127,16 @@ public class MountedContraption extends Contraption {
} }
@Override @Override
public CompoundNBT writeNBT() { public CompoundNBT writeNBT(boolean spawnPacket) {
CompoundNBT writeNBT = super.writeNBT(); CompoundNBT tag = super.writeNBT(spawnPacket);
NBTHelper.writeEnum(writeNBT, "RotationMode", rotationMode); NBTHelper.writeEnum(tag, "RotationMode", rotationMode);
return writeNBT; return tag;
} }
@Override @Override
public void readNBT(World world, CompoundNBT nbt) { public void readNBT(World world, CompoundNBT nbt, boolean spawnData) {
rotationMode = NBTHelper.readEnum(nbt, "RotationMode", CartMovementMode.class); rotationMode = NBTHelper.readEnum(nbt, "RotationMode", CartMovementMode.class);
super.readNBT(world, nbt); super.readNBT(world, nbt, spawnData);
} }
@Override @Override

View file

@ -1,25 +1,11 @@
package com.simibubi.create.content.contraptions.components.structureMovement.piston; package com.simibubi.create.content.contraptions.components.structureMovement.piston;
import static com.simibubi.create.AllBlocks.MECHANICAL_PISTON_HEAD;
import static com.simibubi.create.AllBlocks.PISTON_EXTENSION_POLE;
import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isExtensionPole;
import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isPiston;
import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isPistonHead;
import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isStickyPiston;
import static net.minecraft.state.properties.BlockStateProperties.FACING;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang3.tuple.Pair;
import com.simibubi.create.content.contraptions.components.structureMovement.AllContraptionTypes; import com.simibubi.create.content.contraptions.components.structureMovement.AllContraptionTypes;
import com.simibubi.create.content.contraptions.components.structureMovement.BlockMovementTraits; import com.simibubi.create.content.contraptions.components.structureMovement.BlockMovementTraits;
import com.simibubi.create.content.contraptions.components.structureMovement.TranslatingContraption; import com.simibubi.create.content.contraptions.components.structureMovement.TranslatingContraption;
import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.PistonState; import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.*;
import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.CarpetBlock; import net.minecraft.block.CarpetBlock;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
@ -32,6 +18,15 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IWorld; import net.minecraft.world.IWorld;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.gen.feature.template.Template.BlockInfo; import net.minecraft.world.gen.feature.template.Template.BlockInfo;
import org.apache.commons.lang3.tuple.Pair;
import java.util.ArrayList;
import java.util.List;
import static com.simibubi.create.AllBlocks.MECHANICAL_PISTON_HEAD;
import static com.simibubi.create.AllBlocks.PISTON_EXTENSION_POLE;
import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.*;
import static net.minecraft.state.properties.BlockStateProperties.FACING;
public class PistonContraption extends TranslatingContraption { public class PistonContraption extends TranslatingContraption {
@ -77,8 +72,7 @@ public class PistonContraption extends TranslatingContraption {
return false; return false;
if (blockState.get(MechanicalPistonBlock.STATE) == PistonState.EXTENDED) { if (blockState.get(MechanicalPistonBlock.STATE) == PistonState.EXTENDED) {
while (isExtensionPole(nextBlock) && nextBlock.get(FACING) while (PistonPolePlacementHelper.matchesAxis(nextBlock, direction.getAxis()) || isPistonHead(nextBlock) && nextBlock.get(FACING) == direction) {
.getAxis() == direction.getAxis() || isPistonHead(nextBlock) && nextBlock.get(FACING) == direction) {
actualStart = actualStart.offset(direction); actualStart = actualStart.offset(direction);
poles.add(new BlockInfo(actualStart, nextBlock.with(FACING, direction), null)); poles.add(new BlockInfo(actualStart, nextBlock.with(FACING, direction), null));
@ -105,7 +99,7 @@ public class PistonContraption extends TranslatingContraption {
nextBlock = world.getBlockState(end.offset(direction.getOpposite())); nextBlock = world.getBlockState(end.offset(direction.getOpposite()));
int extensionsInBack = 0; int extensionsInBack = 0;
while (isExtensionPole(nextBlock)) { while (PistonPolePlacementHelper.matchesAxis(nextBlock, direction.getAxis())) {
end = end.offset(direction.getOpposite()); end = end.offset(direction.getOpposite());
poles.add(new BlockInfo(end, nextBlock.with(FACING, direction), null)); poles.add(new BlockInfo(end, nextBlock.with(FACING, direction), null));
extensionsInBack++; extensionsInBack++;
@ -209,20 +203,20 @@ public class PistonContraption extends TranslatingContraption {
} }
@Override @Override
public void readNBT(World world, CompoundNBT nbt) { public void readNBT(World world, CompoundNBT nbt, boolean spawnData) {
super.readNBT(world, nbt); super.readNBT(world, nbt, spawnData);
initialExtensionProgress = nbt.getInt("InitialLength"); initialExtensionProgress = nbt.getInt("InitialLength");
extensionLength = nbt.getInt("ExtensionLength"); extensionLength = nbt.getInt("ExtensionLength");
orientation = Direction.byIndex(nbt.getInt("Orientation")); orientation = Direction.byIndex(nbt.getInt("Orientation"));
} }
@Override @Override
public CompoundNBT writeNBT() { public CompoundNBT writeNBT(boolean spawnPacket) {
CompoundNBT nbt = super.writeNBT(); CompoundNBT tag = super.writeNBT(spawnPacket);
nbt.putInt("InitialLength", initialExtensionProgress); tag.putInt("InitialLength", initialExtensionProgress);
nbt.putInt("ExtensionLength", extensionLength); tag.putInt("ExtensionLength", extensionLength);
nbt.putInt("Orientation", orientation.getIndex()); tag.putInt("Orientation", orientation.getIndex());
return nbt; return tag;
} }
} }

View file

@ -4,10 +4,12 @@ import static com.simibubi.create.content.contraptions.components.structureMovem
import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isPiston; import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isPiston;
import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isPistonHead; import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isPistonHead;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllShapes; import com.simibubi.create.AllShapes;
import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.PistonState; import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.PistonState;
import com.simibubi.create.content.contraptions.wrench.IWrenchable; import com.simibubi.create.content.contraptions.wrench.IWrenchable;
import com.simibubi.create.foundation.block.ProperDirectionalBlock; import com.simibubi.create.foundation.block.ProperDirectionalBlock;
import com.simibubi.create.foundation.utility.Pair;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
@ -17,12 +19,16 @@ import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.fluid.FluidState; import net.minecraft.fluid.FluidState;
import net.minecraft.fluid.Fluids; import net.minecraft.fluid.Fluids;
import net.minecraft.item.BlockItemUseContext; import net.minecraft.item.BlockItemUseContext;
import net.minecraft.item.ItemStack;
import net.minecraft.state.StateContainer.Builder; import net.minecraft.state.StateContainer.Builder;
import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.Axis;
import net.minecraft.util.Direction.AxisDirection; import net.minecraft.util.Direction.AxisDirection;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.shapes.ISelectionContext; import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.world.IBlockReader; import net.minecraft.world.IBlockReader;
@ -31,91 +37,129 @@ import net.minecraft.world.World;
public class PistonExtensionPoleBlock extends ProperDirectionalBlock implements IWrenchable, IWaterLoggable { public class PistonExtensionPoleBlock extends ProperDirectionalBlock implements IWrenchable, IWaterLoggable {
public PistonExtensionPoleBlock(Properties properties) { public PistonExtensionPoleBlock(Properties properties) {
super(properties); super(properties);
setDefaultState(getDefaultState().with(FACING, Direction.UP).with(BlockStateProperties.WATERLOGGED, false)); setDefaultState(getDefaultState().with(FACING, Direction.UP)
} .with(BlockStateProperties.WATERLOGGED, false));
}
@Override @Override
public PushReaction getPushReaction(BlockState state) { public PushReaction getPushReaction(BlockState state) {
return PushReaction.NORMAL; return PushReaction.NORMAL;
} }
@Override @Override
public void onBlockHarvested(World worldIn, BlockPos pos, BlockState state, PlayerEntity player) { public void onBlockHarvested(World worldIn, BlockPos pos, BlockState state, PlayerEntity player) {
Axis axis = state.get(FACING) Axis axis = state.get(FACING)
.getAxis(); .getAxis();
Direction direction = Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis); Direction direction = Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis);
BlockPos pistonHead = null; BlockPos pistonHead = null;
BlockPos pistonBase = null; BlockPos pistonBase = null;
for (int modifier : new int[]{1, -1}) { for (int modifier : new int[] { 1, -1 }) {
for (int offset = modifier; modifier * offset < MechanicalPistonBlock.maxAllowedPistonPoles(); offset += for (int offset = modifier; modifier * offset < MechanicalPistonBlock.maxAllowedPistonPoles(); offset +=
modifier) { modifier) {
BlockPos currentPos = pos.offset(direction, offset); BlockPos currentPos = pos.offset(direction, offset);
BlockState block = worldIn.getBlockState(currentPos); BlockState block = worldIn.getBlockState(currentPos);
if (isExtensionPole(block) && axis == block.get(FACING) if (isExtensionPole(block) && axis == block.get(FACING)
.getAxis()) .getAxis())
continue; continue;
if (isPiston(block) && block.get(BlockStateProperties.FACING) if (isPiston(block) && block.get(BlockStateProperties.FACING)
.getAxis() == axis) .getAxis() == axis)
pistonBase = currentPos; pistonBase = currentPos;
if (isPistonHead(block) && block.get(BlockStateProperties.FACING) if (isPistonHead(block) && block.get(BlockStateProperties.FACING)
.getAxis() == axis) .getAxis() == axis)
pistonHead = currentPos; pistonHead = currentPos;
break; break;
} }
} }
if (pistonHead != null && pistonBase != null && worldIn.getBlockState(pistonHead) if (pistonHead != null && pistonBase != null && worldIn.getBlockState(pistonHead)
.get(BlockStateProperties.FACING) == worldIn.getBlockState(pistonBase) .get(BlockStateProperties.FACING) == worldIn.getBlockState(pistonBase)
.get(BlockStateProperties.FACING)) { .get(BlockStateProperties.FACING)) {
final BlockPos basePos = pistonBase; final BlockPos basePos = pistonBase;
BlockPos.getAllInBox(pistonBase, pistonHead) BlockPos.getAllInBox(pistonBase, pistonHead)
.filter(p -> !p.equals(pos) && !p.equals(basePos)) .filter(p -> !p.equals(pos) && !p.equals(basePos))
.forEach(p -> worldIn.destroyBlock(p, !player.isCreative())); .forEach(p -> worldIn.destroyBlock(p, !player.isCreative()));
worldIn.setBlockState(basePos, worldIn.getBlockState(basePos) worldIn.setBlockState(basePos, worldIn.getBlockState(basePos)
.with(MechanicalPistonBlock.STATE, PistonState.RETRACTED)); .with(MechanicalPistonBlock.STATE, PistonState.RETRACTED));
} }
super.onBlockHarvested(worldIn, pos, state, player); super.onBlockHarvested(worldIn, pos, state, player);
} }
@Override @Override
public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) {
return AllShapes.FOUR_VOXEL_POLE.get(state.get(FACING) return AllShapes.FOUR_VOXEL_POLE.get(state.get(FACING)
.getAxis()); .getAxis());
} }
@Override @Override
public BlockState getStateForPlacement(BlockItemUseContext context) { public BlockState getStateForPlacement(BlockItemUseContext context) {
FluidState FluidState = context.getWorld().getFluidState(context.getPos()); FluidState FluidState = context.getWorld()
return getDefaultState().with(FACING, context.getFace().getOpposite()) .getFluidState(context.getPos());
.with(BlockStateProperties.WATERLOGGED, Boolean.valueOf(FluidState.getFluid() == Fluids.WATER)); return getDefaultState().with(FACING, context.getFace()
} .getOpposite())
.with(BlockStateProperties.WATERLOGGED, Boolean.valueOf(FluidState.getFluid() == Fluids.WATER));
}
@Override @Override
public FluidState getFluidState(BlockState state) { public ActionResultType onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand,
return state.get(BlockStateProperties.WATERLOGGED) ? Fluids.WATER.getStillFluidState(false) : Fluids.EMPTY.getDefaultState(); BlockRayTraceResult ray) {
} ItemStack heldItem = player.getHeldItem(hand);
@Override if (AllBlocks.PISTON_EXTENSION_POLE.isIn(heldItem) && !player.isSneaking()) {
protected void fillStateContainer(Builder<Block, BlockState> builder) { Pair<Direction, Integer> offset = PistonPolePlacementHelper.getPlacementOffset(world, state.get(FACING)
builder.add(BlockStateProperties.WATERLOGGED); .getAxis(), pos, ray.getHitVec());
super.fillStateContainer(builder);
}
@Override if (offset == null || offset.getSecond() == 0)
public BlockState updatePostPlacement(BlockState state, Direction direction, BlockState neighbourState, return ActionResultType.PASS;
IWorld world, BlockPos pos, BlockPos neighbourPos) {
if (state.get(BlockStateProperties.WATERLOGGED)) { BlockPos newPos = pos.offset(offset.getFirst(), offset.getSecond());
world.getPendingFluidTicks().scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickRate(world));
} if (!world.getBlockState(newPos)
return state; .getMaterial()
} .isReplaceable())
return ActionResultType.PASS;
if (world.isRemote)
return ActionResultType.SUCCESS;
world.setBlockState(newPos, AllBlocks.PISTON_EXTENSION_POLE.getDefaultState()
.with(FACING, offset.getFirst()));
if (!player.isCreative())
heldItem.shrink(1);
return ActionResultType.SUCCESS;
}
return ActionResultType.PASS;
}
@Override
public FluidState getFluidState(BlockState state) {
return state.get(BlockStateProperties.WATERLOGGED) ? Fluids.WATER.getStillFluidState(false)
: Fluids.EMPTY.getDefaultState();
}
@Override
protected void fillStateContainer(Builder<Block, BlockState> builder) {
builder.add(BlockStateProperties.WATERLOGGED);
super.fillStateContainer(builder);
}
@Override
public BlockState updatePostPlacement(BlockState state, Direction direction, BlockState neighbourState,
IWorld world, BlockPos pos, BlockPos neighbourPos) {
if (state.get(BlockStateProperties.WATERLOGGED)) {
world.getPendingFluidTicks()
.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickRate(world));
}
return state;
}
} }

View file

@ -0,0 +1,126 @@
package com.simibubi.create.content.contraptions.components.structureMovement.piston;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.CreateClient;
import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.Pair;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import java.util.Arrays;
public class PistonPolePlacementHelper {
@OnlyIn(Dist.CLIENT)
public static void tick() {
Minecraft mc = Minecraft.getInstance();
ClientWorld world = mc.world;
if (!(mc.objectMouseOver instanceof BlockRayTraceResult))
return;
BlockRayTraceResult ray = (BlockRayTraceResult) mc.objectMouseOver;
if (!isHoldingPole(mc.player))
return;
BlockPos pos = ray.getPos();
BlockState state = world.getBlockState(pos);
if (!(state.getBlock() instanceof PistonExtensionPoleBlock))
return;
Pair<Direction, Integer> offset = getPlacementOffset(world, state.get(PistonExtensionPoleBlock.FACING).getAxis(), pos, ray.getHitVec());
if (offset == null || offset.getSecond() == 0)
return;
Direction hitFace = ray.getFace();
if (hitFace.getAxis() == offset.getFirst().getAxis())
return;
Vec3d hitCenter = VecHelper.getCenterOf(pos).add(new Vec3d(hitFace.getDirectionVec()).scale(0.3));
//get the two perpendicular directions to form the arrow
Direction[] directions = Arrays.stream(Direction.Axis.values()).filter(axis -> axis != hitFace.getAxis() && axis != offset.getFirst().getAxis()).map(Iterate::directionsInAxis).findFirst().orElse(new Direction[]{});
Vec3d startOffset = new Vec3d(offset.getFirst().getDirectionVec());
Vec3d start = hitCenter.add(startOffset);
for (Direction dir : directions) {
Vec3d arrowOffset = new Vec3d(dir.getDirectionVec()).scale(.25);
Vec3d target = hitCenter.add(startOffset.scale(0.75)).add(arrowOffset);
CreateClient.outliner.showLine("poleHelp" + offset.getFirst() + dir, start, target).lineWidth(1/16f);
}
}
// first indicates the direction that the position needs to be offset into
// second indicates by how many blocks the position needs to be offset by; is 0 if there was no valid position on either end of the pole
public static Pair<Direction, Integer> getPlacementOffset(World world, Direction.Axis poleAxis, BlockPos pos, Vec3d hit) {
Pair<Direction, Integer> offset = null;
double min = Double.MAX_VALUE;
Vec3d localPos = hit.subtract(VecHelper.getCenterOf(pos));
//find target direction
for (Direction dir : Iterate.directionsInAxis(poleAxis)) {
double distance = new Vec3d(dir.getDirectionVec()).distanceTo(localPos);
if (distance > min)
continue;
min = distance;
offset = Pair.of(dir, 0);
}
if (offset == null)//??
return null;
//check for space at the end of the pole
int poles = attachedPoles(world, pos, offset.getFirst());
BlockState state = world.getBlockState(pos.offset(offset.getFirst(), poles + 1));
if (state.getMaterial().isReplaceable()) {
offset.setSecond(poles + 1);
return offset;
}
//check the other end of the pole
offset.setFirst(offset.getFirst().getOpposite());
poles = attachedPoles(world, pos, offset.getFirst());
state = world.getBlockState(pos.offset(offset.getFirst(), poles + 1));
if (state.getMaterial().isReplaceable()) {
offset.setSecond(poles + 1);
}
return offset;
}
public static int attachedPoles(World world, BlockPos pos, Direction direction) {
BlockPos checkPos = pos.offset(direction);
BlockState state = world.getBlockState(checkPos);
int count = 0;
while (matchesAxis(state, direction.getAxis())) {
count++;
checkPos = checkPos.offset(direction);
state = world.getBlockState(checkPos);
}
return count;
}
//checks if the given state is a piston pole on the given axis
public static boolean matchesAxis(BlockState state, Direction.Axis axis) {
return AllBlocks.PISTON_EXTENSION_POLE.has(state) && state.get(PistonExtensionPoleBlock.FACING).getAxis() == axis;
}
public static boolean isHoldingPole(PlayerEntity player) {
return Arrays.stream(Hand.values()).anyMatch(hand -> AllBlocks.PISTON_EXTENSION_POLE.isIn(player.getHeldItem(hand)));
}
}

View file

@ -41,16 +41,16 @@ public class PulleyContraption extends TranslatingContraption {
} }
@Override @Override
public CompoundNBT writeNBT() { public CompoundNBT writeNBT(boolean spawnPacket) {
CompoundNBT writeNBT = super.writeNBT(); CompoundNBT tag = super.writeNBT(spawnPacket);
writeNBT.putInt("InitialOffset", initialOffset); tag.putInt("InitialOffset", initialOffset);
return writeNBT; return tag;
} }
@Override @Override
public void readNBT(World world, CompoundNBT nbt) { public void readNBT(World world, CompoundNBT nbt, boolean spawnData) {
initialOffset = nbt.getInt("InitialOffset"); initialOffset = nbt.getInt("InitialOffset");
super.readNBT(world, nbt); super.readNBT(world, nbt, spawnData);
} }
} }

View file

@ -0,0 +1,53 @@
package com.simibubi.create.content.contraptions.components.structureMovement.sync;
import java.util.function.Supplier;
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
import com.simibubi.create.foundation.networking.SimplePacketBase;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.Entity;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fml.network.NetworkEvent.Context;
public class ContraptionFluidPacket extends SimplePacketBase {
private int entityId;
private BlockPos localPos;
private FluidStack containedFluid;
public ContraptionFluidPacket(int entityId, BlockPos localPos, FluidStack containedFluid) {
this.entityId = entityId;
this.localPos = localPos;
this.containedFluid = containedFluid;
}
public ContraptionFluidPacket(PacketBuffer buffer) {
entityId = buffer.readInt();
localPos = buffer.readBlockPos();
containedFluid = FluidStack.readFromPacket(buffer);
}
@Override
public void write(PacketBuffer buffer) {
buffer.writeInt(entityId);
buffer.writeBlockPos(localPos);
containedFluid.writeToPacket(buffer);
}
@Override
public void handle(Supplier<Context> context) {
context.get()
.enqueueWork(() -> {
Entity entityByID = Minecraft.getInstance().world.getEntityByID(entityId);
if (!(entityByID instanceof AbstractContraptionEntity))
return;
AbstractContraptionEntity contraptionEntity = (AbstractContraptionEntity) entityByID;
contraptionEntity.getContraption().updateContainedFluid(localPos, containedFluid);
});
context.get()
.setPacketHandled(true);
}
}

View file

@ -68,7 +68,7 @@ public class FluidFX {
vec = VecHelper.clampComponentWise(vec, rimRadius) vec = VecHelper.clampComponentWise(vec, rimRadius)
.mul(VecHelper.axisAlingedPlaneOf(directionVec)) .mul(VecHelper.axisAlingedPlaneOf(directionVec))
.add(directionVec.scale(.45 + r.nextFloat() / 16f)); .add(directionVec.scale(.45 + r.nextFloat() / 16f));
Vector3d m = vec; Vector3d m = vec.scale(.05f);
vec = vec.add(VecHelper.getCenterOf(pos)); vec = vec.add(VecHelper.getCenterOf(pos));
world.addOptionalParticle(particle, vec.x, vec.y - 1 / 16f, vec.z, m.x, m.y, m.z); world.addOptionalParticle(particle, vec.x, vec.y - 1 / 16f, vec.z, m.x, m.y, m.z);

View file

@ -18,7 +18,7 @@ public class CreativeFluidTankTileEntity extends FluidTankTileEntity {
return new CreativeSmartFluidTank(getCapacityMultiplier(), this::onFluidStackChanged); return new CreativeSmartFluidTank(getCapacityMultiplier(), this::onFluidStackChanged);
} }
class CreativeSmartFluidTank extends SmartFluidTank { public static class CreativeSmartFluidTank extends SmartFluidTank {
public CreativeSmartFluidTank(int capacity, Consumer<FluidStack> updateCallback) { public CreativeSmartFluidTank(int capacity, Consumer<FluidStack> updateCallback) {
super(capacity, updateCallback); super(capacity, updateCallback);
@ -33,7 +33,7 @@ public class CreativeFluidTankTileEntity extends FluidTankTileEntity {
fluid = fluidStack.copy(); fluid = fluidStack.copy();
if (!fluidStack.isEmpty()) if (!fluidStack.isEmpty())
fluid.setAmount(getTankCapacity(0)); fluid.setAmount(getTankCapacity(0));
notifyUpdate(); onContentsChanged();
} }
@Override @Override

View file

@ -28,6 +28,8 @@ import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ActionResultType; import net.minecraft.util.ActionResultType;
import net.minecraft.util.Hand; import net.minecraft.util.Hand;
import net.minecraft.util.IStringSerializable; import net.minecraft.util.IStringSerializable;
import net.minecraft.util.Mirror;
import net.minecraft.util.Rotation;
import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvent; import net.minecraft.util.SoundEvent;
import net.minecraft.util.SoundEvents; import net.minecraft.util.SoundEvents;
@ -41,6 +43,7 @@ import net.minecraft.world.World;
import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fluids.FluidAttributes; import net.minecraftforge.fluids.FluidAttributes;
import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandler;
public class FluidTankBlock extends Block implements IWrenchable, ITE<FluidTankTileEntity> { public class FluidTankBlock extends Block implements IWrenchable, ITE<FluidTankTileEntity> {
@ -72,9 +75,11 @@ public class FluidTankBlock extends Block implements IWrenchable, ITE<FluidTankT
} }
@Override @Override
public void onBlockAdded(BlockState state, World world, BlockPos pos, BlockState oldState, boolean p_220082_5_) { public void onBlockAdded(BlockState state, World world, BlockPos pos, BlockState oldState, boolean moved) {
if (oldState.getBlock() == state.getBlock()) if (oldState.getBlock() == state.getBlock())
return; return;
if (moved)
return;
withTileEntityDo(world, pos, FluidTankTileEntity::updateConnectivity); withTileEntityDo(world, pos, FluidTankTileEntity::updateConnectivity);
} }
@ -116,7 +121,7 @@ public class FluidTankBlock extends Block implements IWrenchable, ITE<FluidTankT
if (te == null) if (te == null)
return ActionResultType.FAIL; return ActionResultType.FAIL;
LazyOptional<IFluidHandler> tankCapability = te.fluidCapability; LazyOptional<IFluidHandler> tankCapability = te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY);
if (!tankCapability.isPresent()) if (!tankCapability.isPresent())
return ActionResultType.PASS; return ActionResultType.PASS;
IFluidHandler fluidTank = tankCapability.orElse(null); IFluidHandler fluidTank = tankCapability.orElse(null);
@ -142,7 +147,8 @@ public class FluidTankBlock extends Block implements IWrenchable, ITE<FluidTankT
if (exchange == FluidExchange.ITEM_TO_TANK) { if (exchange == FluidExchange.ITEM_TO_TANK) {
if (creative && !onClient) { if (creative && !onClient) {
FluidStack fluidInItem = EmptyingByBasin.emptyItem(world, heldItem, true).getFirst(); FluidStack fluidInItem = EmptyingByBasin.emptyItem(world, heldItem, true)
.getFirst();
if (!fluidInItem.isEmpty() && fluidTank instanceof CreativeSmartFluidTank) if (!fluidInItem.isEmpty() && fluidTank instanceof CreativeSmartFluidTank)
((CreativeSmartFluidTank) fluidTank).setContainedFluid(fluidInItem); ((CreativeSmartFluidTank) fluidTank).setContainedFluid(fluidInItem);
} }
@ -241,6 +247,47 @@ public class FluidTankBlock extends Block implements IWrenchable, ITE<FluidTankT
return FluidTankTileEntity.class; return FluidTankTileEntity.class;
} }
@Override
public BlockState mirror(BlockState state, Mirror mirror) {
if (mirror == Mirror.NONE)
return state;
boolean x = mirror == Mirror.FRONT_BACK;
switch (state.get(SHAPE)) {
case WINDOW_NE:
return state.with(SHAPE, x ? Shape.WINDOW_NW : Shape.WINDOW_SE);
case WINDOW_NW:
return state.with(SHAPE, x ? Shape.WINDOW_NE : Shape.WINDOW_SW);
case WINDOW_SE:
return state.with(SHAPE, x ? Shape.WINDOW_SW : Shape.WINDOW_NE);
case WINDOW_SW:
return state.with(SHAPE, x ? Shape.WINDOW_SE : Shape.WINDOW_NW);
default:
return state;
}
}
@Override
public BlockState rotate(BlockState state, Rotation rotation) {
for (int i = 0; i < rotation.ordinal(); i++)
state = rotateOnce(state);
return state;
}
private BlockState rotateOnce(BlockState state) {
switch (state.get(SHAPE)) {
case WINDOW_NE:
return state.with(SHAPE, Shape.WINDOW_SE);
case WINDOW_NW:
return state.with(SHAPE, Shape.WINDOW_NE);
case WINDOW_SE:
return state.with(SHAPE, Shape.WINDOW_SW);
case WINDOW_SW:
return state.with(SHAPE, Shape.WINDOW_NW);
default:
return state;
}
}
public enum Shape implements IStringSerializable { public enum Shape implements IStringSerializable {
PLAIN, WINDOW, WINDOW_NW, WINDOW_SW, WINDOW_NE, WINDOW_SE; PLAIN, WINDOW, WINDOW_NW, WINDOW_SW, WINDOW_NE, WINDOW_SE;

View file

@ -14,6 +14,7 @@ import javax.annotation.Nullable;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import com.simibubi.create.content.contraptions.fluids.tank.CreativeFluidTankTileEntity.CreativeSmartFluidTank;
import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Iterate;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
@ -25,8 +26,12 @@ import net.minecraft.util.Direction.AxisDirection;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockReader; import net.minecraft.world.IBlockReader;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction; import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction;
import net.minecraftforge.fluids.capability.templates.FluidTank;
public class FluidTankConnectivityHandler { public class FluidTankConnectivityHandler {
@ -147,8 +152,10 @@ public class FluidTankConnectivityHandler {
TileEntityType<?> type = te.getType(); TileEntityType<?> type = te.getType();
World world = te.getWorld(); World world = te.getWorld();
BlockPos origin = te.getPos(); BlockPos origin = te.getPos();
FluidStack fluid = te.getTankInventory() LazyOptional<IFluidHandler> capability = te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY);
.getFluid(); FluidTank teTank = (FluidTank) capability.orElse(null);
FluidStack fluid = capability.map(ifh -> ifh.getFluidInTank(0))
.orElse(FluidStack.EMPTY);
Search: Search:
@ -192,6 +199,8 @@ public class FluidTankConnectivityHandler {
if (simulate) if (simulate)
return amount; return amount;
boolean opaque = false;
for (int yOffset = 0; yOffset < height; yOffset++) { for (int yOffset = 0; yOffset < height; yOffset++) {
for (int xOffset = 0; xOffset < width; xOffset++) { for (int xOffset = 0; xOffset < width; xOffset++) {
@ -201,10 +210,15 @@ public class FluidTankConnectivityHandler {
if (tank == te) if (tank == te)
continue; continue;
if (tank.isController()) { opaque |= !tank.window;
te.tankInventory.fill(tank.tankInventory.getFluid(), FluidAction.EXECUTE); FluidTank tankTank = tank.tankInventory;
tank.tankInventory.setFluid(FluidStack.EMPTY); FluidStack fluidInTank = tankTank.getFluid();
if (!fluidInTank.isEmpty()) {
if (teTank.isEmpty() && teTank instanceof CreativeSmartFluidTank)
((CreativeSmartFluidTank) teTank).setContainedFluid(fluidInTank);
teTank.fill(fluidInTank, FluidAction.EXECUTE);
} }
tankTank.setFluid(FluidStack.EMPTY);
splitTankAndInvalidate(tank, cache, false); splitTankAndInvalidate(tank, cache, false);
tank.setController(origin); tank.setController(origin);
@ -220,6 +234,8 @@ public class FluidTankConnectivityHandler {
} }
} }
} }
te.setWindows(!opaque);
return amount; return amount;
} }
@ -243,8 +259,9 @@ public class FluidTankConnectivityHandler {
FluidStack toDistribute = te.tankInventory.getFluid() FluidStack toDistribute = te.tankInventory.getFluid()
.copy(); .copy();
int maxCapacity = FluidTankTileEntity.getCapacityMultiplier(); int maxCapacity = FluidTankTileEntity.getCapacityMultiplier();
if (!toDistribute.isEmpty()) if (!toDistribute.isEmpty() && !te.isRemoved())
toDistribute.shrink(maxCapacity); toDistribute.shrink(maxCapacity);
te.applyFluidTankSize(1);
for (int yOffset = 0; yOffset < height; yOffset++) { for (int yOffset = 0; yOffset < height; yOffset++) {
for (int xOffset = 0; xOffset < width; xOffset++) { for (int xOffset = 0; xOffset < width; xOffset++) {
@ -259,14 +276,19 @@ public class FluidTankConnectivityHandler {
continue; continue;
FluidTankTileEntity controllerTE = tankAt.getControllerTE(); FluidTankTileEntity controllerTE = tankAt.getControllerTE();
tankAt.window = controllerTE == null || controllerTE.window; tankAt.window = controllerTE == null || controllerTE.window;
tankAt.removeController(); tankAt.removeController(true);
if (!toDistribute.isEmpty() && tankAt != te) { if (!toDistribute.isEmpty() && tankAt != te) {
int split = Math.min(maxCapacity, toDistribute.getAmount());
FluidStack copy = toDistribute.copy(); FluidStack copy = toDistribute.copy();
copy.setAmount(split); FluidTank tankInventory = tankAt.tankInventory;
toDistribute.shrink(split); if (tankInventory.isEmpty() && tankInventory instanceof CreativeSmartFluidTank)
tankAt.tankInventory.fill(copy, FluidAction.EXECUTE); ((CreativeSmartFluidTank) tankInventory).setContainedFluid(toDistribute);
else {
int split = Math.min(maxCapacity, toDistribute.getAmount());
copy.setAmount(split);
toDistribute.shrink(split);
tankInventory.fill(copy, FluidAction.EXECUTE);
}
} }
if (tryReconnect) { if (tryReconnect) {
@ -300,7 +322,7 @@ public class FluidTankConnectivityHandler {
return (FluidTankTileEntity) te; return (FluidTankTileEntity) te;
return null; return null;
} }
@Nullable @Nullable
public static FluidTankTileEntity anyTankAt(IBlockReader world, BlockPos pos) { public static FluidTankTileEntity anyTankAt(IBlockReader world, BlockPos pos) {
TileEntity te = world.getTileEntity(pos); TileEntity te = world.getTileEntity(pos);

View file

@ -6,10 +6,13 @@ import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.BlockItem; import net.minecraft.item.BlockItem;
import net.minecraft.item.BlockItemUseContext; import net.minecraft.item.BlockItemUseContext;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.ActionResultType; import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.fluids.FluidStack;
public class FluidTankItem extends BlockItem { public class FluidTankItem extends BlockItem {
@ -26,6 +29,30 @@ public class FluidTankItem extends BlockItem {
return initialResult; return initialResult;
} }
@Override
protected boolean onBlockPlaced(BlockPos p_195943_1_, World p_195943_2_, PlayerEntity p_195943_3_,
ItemStack p_195943_4_, BlockState p_195943_5_) {
MinecraftServer minecraftserver = p_195943_2_.getServer();
if (minecraftserver == null)
return false;
CompoundNBT nbt = p_195943_4_.getChildTag("BlockEntityTag");
if (nbt != null) {
nbt.remove("Luminosity");
nbt.remove("Size");
nbt.remove("Height");
nbt.remove("Controller");
nbt.remove("LastKnownPos");
if (nbt.contains("TankContent")) {
FluidStack fluid = FluidStack.loadFluidStackFromNBT(nbt.getCompound("TankContent"));
if (!fluid.isEmpty()) {
fluid.setAmount(Math.min(FluidTankTileEntity.getCapacityMultiplier(), fluid.getAmount()));
nbt.put("TankContent", fluid.writeToNBT(new CompoundNBT()));
}
}
}
return super.onBlockPlaced(p_195943_1_, p_195943_2_, p_195943_3_, p_195943_4_, p_195943_5_);
}
private void tryMultiPlace(BlockItemUseContext ctx) { private void tryMultiPlace(BlockItemUseContext ctx) {
PlayerEntity player = ctx.getPlayer(); PlayerEntity player = ctx.getPlayer();
if (player == null) if (player == null)

View file

@ -42,6 +42,7 @@ public class FluidTankTileEntity extends SmartTileEntity {
protected boolean forceFluidLevelUpdate; protected boolean forceFluidLevelUpdate;
protected FluidTank tankInventory; protected FluidTank tankInventory;
protected BlockPos controller; protected BlockPos controller;
protected BlockPos lastKnownPos;
protected boolean updateConnectivity; protected boolean updateConnectivity;
protected boolean window; protected boolean window;
protected int luminosity; protected int luminosity;
@ -88,6 +89,14 @@ public class FluidTankTileEntity extends SmartTileEntity {
if (syncCooldown == 0 && queuedSync) if (syncCooldown == 0 && queuedSync)
sendData(); sendData();
} }
if (lastKnownPos == null)
lastKnownPos = getPos();
else if (!lastKnownPos.equals(pos) && pos != null) {
onPositionChanged();
return;
}
if (updateConnectivity) if (updateConnectivity)
updateConnectivity(); updateConnectivity();
if (fluidLevel != null) if (fluidLevel != null)
@ -104,6 +113,11 @@ public class FluidTankTileEntity extends SmartTileEntity {
sendData(); sendData();
} }
private void onPositionChanged() {
removeController(true);
lastKnownPos = pos;
}
protected void onFluidStackChanged(FluidStack newFluidStack) { protected void onFluidStackChanged(FluidStack newFluidStack) {
if (!hasWorld()) if (!hasWorld())
return; return;
@ -163,11 +177,12 @@ public class FluidTankTileEntity extends SmartTileEntity {
forceFluidLevelUpdate = true; forceFluidLevelUpdate = true;
} }
public void removeController() { public void removeController(boolean keepFluids) {
if (world.isRemote) if (world.isRemote)
return; return;
updateConnectivity = true; updateConnectivity = true;
applyFluidTankSize(1); if (!keepFluids)
applyFluidTankSize(1);
controller = null; controller = null;
width = 1; width = 1;
height = 1; height = 1;
@ -292,7 +307,10 @@ public class FluidTankTileEntity extends SmartTileEntity {
updateConnectivity = compound.contains("Uninitialized"); updateConnectivity = compound.contains("Uninitialized");
luminosity = compound.getInt("Luminosity"); luminosity = compound.getInt("Luminosity");
controller = null; controller = null;
lastKnownPos = null;
if (compound.contains("LastKnownPos"))
lastKnownPos = NBTUtil.readBlockPos(compound.getCompound("LastKnownPos"));
if (compound.contains("Controller")) if (compound.contains("Controller"))
controller = NBTUtil.readBlockPos(compound.getCompound("Controller")); controller = NBTUtil.readBlockPos(compound.getCompound("Controller"));
@ -336,7 +354,7 @@ public class FluidTankTileEntity extends SmartTileEntity {
fluidLevel.withSpeed(compound.contains("LazySync") ? 1 / 8f : 1 / 2f); fluidLevel.withSpeed(compound.contains("LazySync") ? 1 / 8f : 1 / 2f);
} }
protected float getFillState() { public float getFillState() {
return (float) tankInventory.getFluidAmount() / tankInventory.getCapacity(); return (float) tankInventory.getFluidAmount() / tankInventory.getCapacity();
} }
@ -344,6 +362,8 @@ public class FluidTankTileEntity extends SmartTileEntity {
public void write(CompoundNBT compound, boolean clientPacket) { public void write(CompoundNBT compound, boolean clientPacket) {
if (updateConnectivity) if (updateConnectivity)
compound.putBoolean("Uninitialized", true); compound.putBoolean("Uninitialized", true);
if (lastKnownPos != null)
compound.put("LastKnownPos", NBTUtil.writeBlockPos(lastKnownPos));
if (!isController()) if (!isController())
compound.put("Controller", NBTUtil.writeBlockPos(controller)); compound.put("Controller", NBTUtil.writeBlockPos(controller));
if (isController()) { if (isController()) {
@ -394,12 +414,20 @@ public class FluidTankTileEntity extends SmartTileEntity {
return MAX_SIZE; return MAX_SIZE;
} }
protected static int getCapacityMultiplier() { public static int getCapacityMultiplier() {
return AllConfigs.SERVER.fluids.fluidTankCapacity.get() * 1000; return AllConfigs.SERVER.fluids.fluidTankCapacity.get() * 1000;
} }
public static int getMaxHeight() { public static int getMaxHeight() {
return AllConfigs.SERVER.fluids.fluidTankMaxHeight.get(); return AllConfigs.SERVER.fluids.fluidTankMaxHeight.get();
} }
public InterpolatedChasingValue getFluidLevel() {
return fluidLevel;
}
public void setFluidLevel(InterpolatedChasingValue fluidLevel) {
this.fluidLevel = fluidLevel;
}
} }

View file

@ -4,16 +4,23 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock;
import com.simibubi.create.content.contraptions.components.structureMovement.piston.PistonExtensionPoleBlock;
import com.simibubi.create.content.contraptions.components.structureMovement.piston.PistonPolePlacementHelper;
import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.gui.GuiGameElement; import com.simibubi.create.foundation.gui.GuiGameElement;
import com.simibubi.create.foundation.utility.Iterate;
import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.world.ClientWorld; import net.minecraft.client.world.ClientWorld;
import net.minecraft.inventory.EquipmentSlotType; import net.minecraft.inventory.EquipmentSlotType;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult; import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.math.RayTraceResult;
@ -28,7 +35,6 @@ import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
@EventBusSubscriber(value = Dist.CLIENT) @EventBusSubscriber(value = Dist.CLIENT)
public class GoggleOverlayRenderer { public class GoggleOverlayRenderer {
@SubscribeEvent @SubscribeEvent
public static void lookingAtBlocksThroughGogglesShowsTooltip(RenderGameOverlayEvent.Post event) { public static void lookingAtBlocksThroughGogglesShowsTooltip(RenderGameOverlayEvent.Post event) {
MatrixStack ms = event.getMatrixStack(); MatrixStack ms = event.getMatrixStack();
@ -43,51 +49,83 @@ public class GoggleOverlayRenderer {
Minecraft mc = Minecraft.getInstance(); Minecraft mc = Minecraft.getInstance();
ClientWorld world = mc.world; ClientWorld world = mc.world;
BlockPos pos = result.getPos(); BlockPos pos = result.getPos();
ItemStack goggles = mc.player.getItemStackFromSlot(EquipmentSlotType.HEAD); ItemStack headSlot = mc.player.getItemStackFromSlot(EquipmentSlotType.HEAD);
TileEntity te = world.getTileEntity(pos); TileEntity te = world.getTileEntity(pos);
boolean goggleInformation = te instanceof IHaveGoggleInformation; boolean wearingGoggles = AllItems.GOGGLES.isIn(headSlot);
boolean hoveringInformation = te instanceof IHaveHoveringInformation;
if (!goggleInformation && !hoveringInformation) boolean hasGoggleInformation = te instanceof IHaveGoggleInformation;
return; boolean hasHoveringInformation = te instanceof IHaveHoveringInformation;
boolean goggleAddedInformation = false;
boolean hoverAddedInformation = false;
List<ITextComponent> tooltip = new ArrayList<>(); List<ITextComponent> tooltip = new ArrayList<>();
if (goggleInformation && AllItems.GOGGLES.isIn(goggles)) { if (hasGoggleInformation && wearingGoggles) {
IHaveGoggleInformation gte = (IHaveGoggleInformation) te; IHaveGoggleInformation gte = (IHaveGoggleInformation) te;
if (!gte.addToGoggleTooltip(tooltip, mc.player.isSneaking())) goggleAddedInformation = gte.addToGoggleTooltip(tooltip, mc.player.isSneaking());
goggleInformation = false;
} }
if (hoveringInformation) { if (hasHoveringInformation) {
boolean goggleAddedInformation = !tooltip.isEmpty(); if (!tooltip.isEmpty())
if (goggleAddedInformation)
tooltip.add(StringTextComponent.EMPTY); tooltip.add(StringTextComponent.EMPTY);
IHaveHoveringInformation hte = (IHaveHoveringInformation) te; IHaveHoveringInformation hte = (IHaveHoveringInformation) te;
if (!hte.addToTooltip(tooltip, mc.player.isSneaking())) hoverAddedInformation = hte.addToTooltip(tooltip, mc.player.isSneaking());
hoveringInformation = false;
if (goggleAddedInformation && !hoveringInformation) if (goggleAddedInformation && !hoverAddedInformation)
tooltip.remove(tooltip.size() - 1); tooltip.remove(tooltip.size() - 1);
} }
if (!goggleInformation && !hoveringInformation) // break early if goggle or hover returned false when present
if ((hasGoggleInformation && !goggleAddedInformation) && (hasHoveringInformation && !hoverAddedInformation))
return; return;
// check for piston poles if goggles are worn
BlockState state = world.getBlockState(pos);
if (wearingGoggles && AllBlocks.PISTON_EXTENSION_POLE.has(state)) {
Direction[] directions = Iterate.directionsInAxis(state.get(PistonExtensionPoleBlock.FACING)
.getAxis());
int poles = 1;
boolean pistonFound = false;
for (Direction dir : directions) {
int attachedPoles = PistonPolePlacementHelper.attachedPoles(world, pos, dir);
poles += attachedPoles;
pistonFound |= world.getBlockState(pos.offset(dir, attachedPoles + 1))
.getBlock() instanceof MechanicalPistonBlock;
}
if (!pistonFound)
return;
if (!tooltip.isEmpty())
tooltip.add(StringTextComponent.EMPTY);
tooltip.add(IHaveGoggleInformation.componentSpacing.copy().append(new StringTextComponent("Pole length: " + poles)));
}
if (tooltip.isEmpty()) if (tooltip.isEmpty())
return; return;
ms.push(); ms.push();
Screen tooltipScreen = new TooltipScreen(null); Screen tooltipScreen = new TooltipScreen(null);
tooltipScreen.init(mc, mc.getWindow().getScaledWidth(), mc.getWindow().getScaledHeight()); tooltipScreen.init(mc, mc.getWindow()
.getScaledWidth(),
mc.getWindow()
.getScaledHeight());
int posX = tooltipScreen.width / 2 + AllConfigs.CLIENT.overlayOffsetX.get(); int posX = tooltipScreen.width / 2 + AllConfigs.CLIENT.overlayOffsetX.get();
int posY = tooltipScreen.height / 2 + AllConfigs.CLIENT.overlayOffsetY.get(); int posY = tooltipScreen.height / 2 + AllConfigs.CLIENT.overlayOffsetY.get();
// tooltipScreen.renderTooltip(tooltip, tooltipScreen.width / 2,
// tooltipScreen.height / 2);
tooltipScreen.renderTooltip(ms, tooltip, posX, posY); tooltipScreen.renderTooltip(ms, tooltip, posX, posY);
ItemStack item = AllItems.GOGGLES.asStack(); ItemStack item = AllItems.GOGGLES.asStack();
GuiGameElement.of(item).atLocal(posX + 10, posY, 450).render(ms); // GuiGameElement.of(item).at(tooltipScreen.width / 2 + 10, tooltipScreen.height
// / 2 - 16).render();
GuiGameElement.of(item)
.atLocal(posX + 10, posY, 450)
.render(ms);
ms.pop(); ms.pop();
} }
private static final class TooltipScreen extends Screen { private static final class TooltipScreen extends Screen {
private TooltipScreen(ITextComponent p_i51108_1_) { private TooltipScreen(ITextComponent p_i51108_1_) {

View file

@ -8,6 +8,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.Mov
import net.minecraft.entity.item.ItemEntity; import net.minecraft.entity.item.ItemEntity;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.math.vector.Vector3d; import net.minecraft.util.math.vector.Vector3d;
import net.minecraftforge.items.ItemStackHandler; import net.minecraftforge.items.ItemStackHandler;
@ -51,10 +52,9 @@ public class BasinMovementBehaviour extends MovementBehaviour {
} }
context.tileData.put(key, itemStackHandler.serializeNBT()); context.tileData.put(key, itemStackHandler.serializeNBT());
}); });
context.contraption.renderedTileEntities.stream() TileEntity tileEntity = context.contraption.renderedTileEntities.get(context.localPos);
.filter(te -> te.getPos() if (tileEntity instanceof BasinTileEntity)
.equals(context.localPos) && te instanceof BasinTileEntity) ((BasinTileEntity) tileEntity).readOnlyItems(context.tileData);
.forEach(te -> ((BasinTileEntity) te).readOnlyItems(context.tileData));
context.temporaryData = false; // did already dump, so can't any more context.temporaryData = false; // did already dump, so can't any more
} }
} }

View file

@ -3,7 +3,6 @@ package com.simibubi.create.content.logistics.block.inventories;
import com.simibubi.create.AllShapes; import com.simibubi.create.AllShapes;
import com.simibubi.create.content.contraptions.wrench.IWrenchable; import com.simibubi.create.content.contraptions.wrench.IWrenchable;
import com.simibubi.create.foundation.block.ProperDirectionalBlock; import com.simibubi.create.foundation.block.ProperDirectionalBlock;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.item.BlockItemUseContext; import net.minecraft.item.BlockItemUseContext;
@ -80,6 +79,11 @@ public class CrateBlock extends ProperDirectionalBlock implements IWrenchable {
return getDefaultState(); return getDefaultState();
} }
@Override
public BlockState getRotatedBlockState(BlockState originalState, Direction targetedFace) {
return originalState;
}
@Override @Override
protected void fillStateContainer(Builder<Block, BlockState> builder) { protected void fillStateContainer(Builder<Block, BlockState> builder) {
super.fillStateContainer(builder.add(DOUBLE)); super.fillStateContainer(builder.add(DOUBLE));

View file

@ -1,14 +1,7 @@
package com.simibubi.create.content.logistics.block.redstone; package com.simibubi.create.content.logistics.block.redstone;
import java.util.Random;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.wrench.IWrenchable;
import com.simibubi.create.foundation.block.ProperDirectionalBlock; import com.simibubi.create.foundation.block.ProperDirectionalBlock;
import mcp.MethodsReturnNonnullByDefault; import mcp.MethodsReturnNonnullByDefault;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
@ -23,9 +16,13 @@ import net.minecraft.world.IWorld;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.server.ServerWorld; import net.minecraft.world.server.ServerWorld;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.Random;
@ParametersAreNonnullByDefault @ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault @MethodsReturnNonnullByDefault
public class RedstoneContactBlock extends ProperDirectionalBlock implements IWrenchable { public class RedstoneContactBlock extends ProperDirectionalBlock {
public static final BooleanProperty POWERED = BlockStateProperties.POWERED; public static final BooleanProperty POWERED = BlockStateProperties.POWERED;

View file

@ -2,13 +2,11 @@ package com.simibubi.create.content.logistics.block.redstone;
import com.simibubi.create.AllShapes; import com.simibubi.create.AllShapes;
import com.simibubi.create.AllTileEntities; import com.simibubi.create.AllTileEntities;
import com.simibubi.create.content.contraptions.wrench.IWrenchable;
import com.simibubi.create.content.logistics.block.funnel.FunnelBlock; import com.simibubi.create.content.logistics.block.funnel.FunnelBlock;
import com.simibubi.create.foundation.block.ITE; import com.simibubi.create.foundation.block.ITE;
import com.simibubi.create.foundation.block.ProperDirectionalBlock; import com.simibubi.create.foundation.block.ProperDirectionalBlock;
import com.simibubi.create.foundation.utility.BlockHelper; import com.simibubi.create.foundation.utility.BlockHelper;
import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Iterate;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
@ -29,7 +27,7 @@ import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorldReader; import net.minecraft.world.IWorldReader;
import net.minecraft.world.World; import net.minecraft.world.World;
public class RedstoneLinkBlock extends ProperDirectionalBlock implements ITE<RedstoneLinkTileEntity>, IWrenchable { public class RedstoneLinkBlock extends ProperDirectionalBlock implements ITE<RedstoneLinkTileEntity> {
public static final BooleanProperty POWERED = BlockStateProperties.POWERED; public static final BooleanProperty POWERED = BlockStateProperties.POWERED;
public static final BooleanProperty RECEIVER = BooleanProperty.create("receiver"); public static final BooleanProperty RECEIVER = BooleanProperty.create("receiver");
@ -153,7 +151,12 @@ public class RedstoneLinkBlock extends ProperDirectionalBlock implements ITE<Red
public ActionResultType onWrenched(BlockState state, ItemUseContext context) { public ActionResultType onWrenched(BlockState state, ItemUseContext context) {
if (toggleMode(state, context.getWorld(), context.getPos()) == ActionResultType.SUCCESS) if (toggleMode(state, context.getWorld(), context.getPos()) == ActionResultType.SUCCESS)
return ActionResultType.SUCCESS; return ActionResultType.SUCCESS;
return IWrenchable.super.onWrenched(state, context); return super.onWrenched(state, context);
}
@Override
public BlockState getRotatedBlockState(BlockState originalState, Direction _targetedFace) {
return originalState;
} }
@Override @Override

View file

@ -1,8 +1,5 @@
package com.simibubi.create.events; package com.simibubi.create.events;
import java.util.ArrayList;
import java.util.List;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.Create; import com.simibubi.create.Create;
import com.simibubi.create.CreateClient; import com.simibubi.create.CreateClient;
@ -10,6 +7,7 @@ import com.simibubi.create.content.contraptions.KineticDebugger;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionHandler; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionHandler;
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.SailBlockPlacementHelper; import com.simibubi.create.content.contraptions.components.structureMovement.bearing.SailBlockPlacementHelper;
import com.simibubi.create.content.contraptions.components.structureMovement.chassis.ChassisRangeDisplay; import com.simibubi.create.content.contraptions.components.structureMovement.chassis.ChassisRangeDisplay;
import com.simibubi.create.content.contraptions.components.structureMovement.piston.PistonPolePlacementHelper;
import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingHandlerClient; import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingHandlerClient;
import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingPhysics; import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingPhysics;
import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingRenderer; import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingRenderer;
@ -31,7 +29,6 @@ import com.simibubi.create.foundation.tileEntity.behaviour.linked.LinkRenderer;
import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueRenderer; import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueRenderer;
import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.ServerSpeedProvider; import com.simibubi.create.foundation.utility.ServerSpeedProvider;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.ActiveRenderInfo; import net.minecraft.client.renderer.ActiveRenderInfo;
import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.IRenderTypeBuffer;
@ -52,6 +49,9 @@ import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber; import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
import java.util.ArrayList;
import java.util.List;
@EventBusSubscriber(value = Dist.CLIENT) @EventBusSubscriber(value = Dist.CLIENT)
public class ClientEvents { public class ClientEvents {
@ -95,6 +95,7 @@ public class ClientEvents {
// CollisionDebugger.tick(); // CollisionDebugger.tick();
ArmInteractionPointHandler.tick(); ArmInteractionPointHandler.tick();
SailBlockPlacementHelper.tick(); SailBlockPlacementHelper.tick();
PistonPolePlacementHelper.tick();
CreateClient.outliner.tickOutlines(); CreateClient.outliner.tickOutlines();
} }

View file

@ -1,14 +1,17 @@
package com.simibubi.create.foundation.block; package com.simibubi.create.foundation.block;
import com.simibubi.create.content.contraptions.wrench.IWrenchable;
import com.simibubi.create.foundation.utility.DirectionHelper;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.DirectionalBlock; import net.minecraft.block.DirectionalBlock;
import net.minecraft.item.BlockItemUseContext; import net.minecraft.item.BlockItemUseContext;
import net.minecraft.state.StateContainer.Builder; import net.minecraft.state.StateContainer.Builder;
import net.minecraft.util.Direction;
import net.minecraft.util.Mirror; import net.minecraft.util.Mirror;
import net.minecraft.util.Rotation; import net.minecraft.util.Rotation;
public class ProperDirectionalBlock extends DirectionalBlock { public class ProperDirectionalBlock extends DirectionalBlock implements IWrenchable {
public ProperDirectionalBlock(Properties p_i48415_1_) { public ProperDirectionalBlock(Properties p_i48415_1_) {
super(p_i48415_1_); super(p_i48415_1_);
@ -19,7 +22,19 @@ public class ProperDirectionalBlock extends DirectionalBlock {
builder.add(FACING); builder.add(FACING);
super.fillStateContainer(builder); super.fillStateContainer(builder);
} }
@Override
public BlockState getRotatedBlockState(BlockState originalState, Direction targetedFace) {
Direction facing = originalState.get(FACING);
if (facing.getAxis() == targetedFace.getAxis())
return originalState;
Direction newFacing = DirectionHelper.rotateAround(facing, targetedFace.getAxis());
return originalState.with(FACING, newFacing);
}
@Override @Override
public BlockState getStateForPlacement(BlockItemUseContext context) { public BlockState getStateForPlacement(BlockItemUseContext context) {
return getDefaultState().with(FACING, context.getNearestLookingDirection()); return getDefaultState().with(FACING, context.getNearestLookingDirection());

View file

@ -164,12 +164,6 @@ public class ContinuousOBBCollider extends OBBCollider {
return true; return true;
} }
public Vector3d getAllowedMotion(Vector3d motion) {
double length = motion.length();
return motion.normalize()
.scale(getTimeOfImpact() * length);
}
public Vector3d asSeparationVec(double obbStepHeight) { public Vector3d asSeparationVec(double obbStepHeight) {
if (isDiscreteCollision) { if (isDiscreteCollision) {
if (stepSeparation <= obbStepHeight) if (stepSeparation <= obbStepHeight)

View file

@ -499,7 +499,13 @@ public class StandardRecipeGen extends CreateRecipeProvider {
.patternLine(" I ")), .patternLine(" I ")),
PORTABLE_STORAGE_INTERFACE = create(AllBlocks.PORTABLE_STORAGE_INTERFACE).unlockedBy(I::brassCasing) PORTABLE_STORAGE_INTERFACE = create(AllBlocks.PORTABLE_STORAGE_INTERFACE).unlockedBy(I::brassCasing)
.viaShaped(b -> b.key('I', AllBlocks.REDSTONE_CONTACT.get()) .viaShaped(b -> b.key('I', I.brassCasing())
.key('B', AllBlocks.ANDESITE_FUNNEL.get())
.patternLine(" B ")
.patternLine(" I ")),
PORTABLE_FLUID_INTERFACE = create(AllBlocks.PORTABLE_FLUID_INTERFACE).unlockedBy(I::copperCasing)
.viaShaped(b -> b.key('I', I.copperCasing())
.key('B', AllBlocks.ANDESITE_FUNNEL.get()) .key('B', AllBlocks.ANDESITE_FUNNEL.get())
.patternLine(" B ") .patternLine(" B ")
.patternLine(" I ")), .patternLine(" I ")),

View file

@ -5,9 +5,11 @@ import java.util.function.Function;
import java.util.function.Supplier; import java.util.function.Supplier;
import com.simibubi.create.Create; import com.simibubi.create.Create;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionDisassemblyPacket;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionStallPacket; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionStallPacket;
import com.simibubi.create.content.contraptions.components.structureMovement.glue.GlueEffectPacket; import com.simibubi.create.content.contraptions.components.structureMovement.glue.GlueEffectPacket;
import com.simibubi.create.content.contraptions.components.structureMovement.sync.ClientMotionPacket; import com.simibubi.create.content.contraptions.components.structureMovement.sync.ClientMotionPacket;
import com.simibubi.create.content.contraptions.components.structureMovement.sync.ContraptionFluidPacket;
import com.simibubi.create.content.contraptions.components.structureMovement.sync.ContraptionInteractionPacket; import com.simibubi.create.content.contraptions.components.structureMovement.sync.ContraptionInteractionPacket;
import com.simibubi.create.content.contraptions.components.structureMovement.sync.ContraptionSeatMappingPacket; import com.simibubi.create.content.contraptions.components.structureMovement.sync.ContraptionSeatMappingPacket;
import com.simibubi.create.content.contraptions.components.structureMovement.sync.LimbSwingUpdatePacket; import com.simibubi.create.content.contraptions.components.structureMovement.sync.LimbSwingUpdatePacket;
@ -25,8 +27,8 @@ import com.simibubi.create.content.logistics.packet.ConfigureStockswitchPacket;
import com.simibubi.create.content.schematics.packet.ConfigureSchematicannonPacket; import com.simibubi.create.content.schematics.packet.ConfigureSchematicannonPacket;
import com.simibubi.create.content.schematics.packet.InstantSchematicPacket; import com.simibubi.create.content.schematics.packet.InstantSchematicPacket;
import com.simibubi.create.content.schematics.packet.SchematicPlacePacket; import com.simibubi.create.content.schematics.packet.SchematicPlacePacket;
import com.simibubi.create.content.schematics.packet.SchematicUploadPacket;
import com.simibubi.create.content.schematics.packet.SchematicSyncPacket; import com.simibubi.create.content.schematics.packet.SchematicSyncPacket;
import com.simibubi.create.content.schematics.packet.SchematicUploadPacket;
import com.simibubi.create.foundation.command.ConfigureConfigPacket; import com.simibubi.create.foundation.command.ConfigureConfigPacket;
import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringCountUpdatePacket; import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringCountUpdatePacket;
import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueUpdatePacket; import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueUpdatePacket;
@ -69,11 +71,13 @@ public enum AllPackets {
BEAM_EFFECT(ZapperBeamPacket.class, ZapperBeamPacket::new), BEAM_EFFECT(ZapperBeamPacket.class, ZapperBeamPacket::new),
CONFIGURE_CONFIG(ConfigureConfigPacket.class, ConfigureConfigPacket::new), CONFIGURE_CONFIG(ConfigureConfigPacket.class, ConfigureConfigPacket::new),
CONTRAPTION_STALL(ContraptionStallPacket.class, ContraptionStallPacket::new), CONTRAPTION_STALL(ContraptionStallPacket.class, ContraptionStallPacket::new),
CONTRAPTION_DISASSEMBLE(ContraptionDisassemblyPacket.class, ContraptionDisassemblyPacket::new),
GLUE_EFFECT(GlueEffectPacket.class, GlueEffectPacket::new), GLUE_EFFECT(GlueEffectPacket.class, GlueEffectPacket::new),
CONTRAPTION_SEAT_MAPPING(ContraptionSeatMappingPacket.class, ContraptionSeatMappingPacket::new), CONTRAPTION_SEAT_MAPPING(ContraptionSeatMappingPacket.class, ContraptionSeatMappingPacket::new),
LIMBSWING_UPDATE(LimbSwingUpdatePacket.class, LimbSwingUpdatePacket::new), LIMBSWING_UPDATE(LimbSwingUpdatePacket.class, LimbSwingUpdatePacket::new),
MINECART_CONTROLLER(MinecartControllerUpdatePacket.class, MinecartControllerUpdatePacket::new), MINECART_CONTROLLER(MinecartControllerUpdatePacket.class, MinecartControllerUpdatePacket::new),
FLUID_SPLASH(FluidSplashPacket.class, FluidSplashPacket::new), FLUID_SPLASH(FluidSplashPacket.class, FluidSplashPacket::new),
CONTRAPTION_FLUID(ContraptionFluidPacket.class, ContraptionFluidPacket::new),
; ;

View file

@ -1,17 +1,17 @@
package com.simibubi.create.foundation.utility; package com.simibubi.create.foundation.utility;
import java.util.Arrays;
import java.util.List;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import java.util.Arrays;
import java.util.List;
public class Iterate { public class Iterate {
public static final boolean[] trueAndFalse = { true, false }; public static final boolean[] trueAndFalse = {true, false};
public static final int[] zeroAndOne = { 0, 1 }; public static final int[] zeroAndOne = {0, 1};
public static final int[] positiveAndNegative = { 1, -1 }; public static final int[] positiveAndNegative = {1, -1};
public static final Direction[] directions = Direction.values(); public static final Direction[] directions = Direction.values();
public static final Direction[] horizontalDirections = getHorizontals(); public static final Direction[] horizontalDirections = getHorizontals();
public static final Axis[] axes = Axis.values(); public static final Axis[] axes = Axis.values();
@ -22,10 +22,20 @@ public class Iterate {
directions[i] = Direction.byHorizontalIndex(i); directions[i] = Direction.byHorizontalIndex(i);
return directions; return directions;
} }
public static Direction[] directionsInAxis(Axis axis) {
switch (axis) {
case X:
return new Direction[]{Direction.EAST, Direction.WEST};
case Y:
return new Direction[]{Direction.UP, Direction.DOWN};
default:
case Z:
return new Direction[]{Direction.SOUTH, Direction.NORTH};
}
}
public static List<BlockPos> hereAndBelow(BlockPos pos) { public static List<BlockPos> hereAndBelow(BlockPos pos) {
return Arrays.asList(pos, pos.down()); return Arrays.asList(pos, pos.down());
} }
} }

View file

@ -12,7 +12,6 @@ import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.client.renderer.tileentity.TileEntityRenderer; import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
import net.minecraft.crash.ReportedException;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.vector.Matrix4f; import net.minecraft.util.math.vector.Matrix4f;
@ -20,14 +19,14 @@ import net.minecraft.util.math.vector.Vector4f;
import net.minecraft.world.World; import net.minecraft.world.World;
public class TileEntityRenderHelper { public class TileEntityRenderHelper {
public static void renderTileEntities(World world, Iterable<TileEntity> customRenderTEs, MatrixStack ms, public static void renderTileEntities(World world, Iterable<TileEntity> customRenderTEs, MatrixStack ms,
MatrixStack localTransform, IRenderTypeBuffer buffer) { MatrixStack localTransform, IRenderTypeBuffer buffer) {
float pt = Minecraft.getInstance() float pt = Minecraft.getInstance()
.getRenderPartialTicks(); .getRenderPartialTicks();
Matrix4f matrix = localTransform.peek() Matrix4f matrix = localTransform.peek()
.getModel(); .getModel();
for (Iterator<TileEntity> iterator = customRenderTEs.iterator(); iterator.hasNext();) { for (Iterator<TileEntity> iterator = customRenderTEs.iterator(); iterator.hasNext();) {
TileEntity tileEntity = iterator.next(); TileEntity tileEntity = iterator.next();
TileEntityRenderer<TileEntity> renderer = TileEntityRendererDispatcher.instance.getRenderer(tileEntity); TileEntityRenderer<TileEntity> renderer = TileEntityRendererDispatcher.instance.getRenderer(tileEntity);
@ -49,17 +48,18 @@ public class TileEntityRenderHelper {
OverlayTexture.DEFAULT_UV); OverlayTexture.DEFAULT_UV);
ms.pop(); ms.pop();
} catch (ReportedException e) { } catch (Exception e) {
if (AllConfigs.CLIENT.explainRenderErrors.get()) {
Create.logger.error("TileEntity " + tileEntity.getType()
.getRegistryName()
.toString() + " didn't want to render while moved.\n", e);
} else {
Create.logger.error("TileEntity " + tileEntity.getType()
.getRegistryName()
.toString() + " didn't want to render while moved.\n");
}
iterator.remove(); iterator.remove();
String message = "TileEntity " + tileEntity.getType()
.getRegistryName()
.toString() + " didn't want to render while moved.\n";
if (AllConfigs.CLIENT.explainRenderErrors.get()) {
Create.logger.error(message, e);
continue;
}
Create.logger.error(message);
continue; continue;
} }
} }

View file

@ -1,21 +1,30 @@
package com.simibubi.create.foundation.utility.worldWrappers; package com.simibubi.create.foundation.utility.worldWrappers;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.function.Predicate; import java.util.function.Predicate;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
public class PlacementSimulationWorld extends WrappedWorld { public class PlacementSimulationWorld extends WrappedWorld {
public HashMap<BlockPos, BlockState> blocksAdded; public HashMap<BlockPos, BlockState> blocksAdded;
public HashMap<BlockPos, TileEntity> tesAdded;
public PlacementSimulationWorld(World wrapped) { public PlacementSimulationWorld(World wrapped) {
super(wrapped); super(wrapped);
blocksAdded = new HashMap<>(); blocksAdded = new HashMap<>();
tesAdded = new HashMap<>();
} }
public void setTileEntities(Collection<TileEntity> tileEntities) {
tesAdded.clear();
tileEntities.forEach(te -> tesAdded.put(te.getPos(), te));
}
public void clear() { public void clear() {
blocksAdded.clear(); blocksAdded.clear();
} }
@ -31,16 +40,21 @@ public class PlacementSimulationWorld extends WrappedWorld {
return setBlockState(pos, state, 0); return setBlockState(pos, state, 0);
} }
@Override
public TileEntity getTileEntity(BlockPos pos) {
return tesAdded.get(pos);
}
@Override @Override
public boolean hasBlockState(BlockPos pos, Predicate<BlockState> condition) { public boolean hasBlockState(BlockPos pos, Predicate<BlockState> condition) {
return condition.test(getBlockState(pos)); return condition.test(getBlockState(pos));
} }
@Override @Override
public boolean isBlockPresent(BlockPos pos) { public boolean isBlockPresent(BlockPos pos) {
return true; return true;
} }
@Override @Override
public boolean isAreaLoaded(BlockPos center, int range) { public boolean isAreaLoaded(BlockPos center, int range) {
return true; return true;
@ -52,5 +66,5 @@ public class PlacementSimulationWorld extends WrappedWorld {
return blocksAdded.get(pos); return blocksAdded.get(pos);
return Blocks.AIR.getDefaultState(); return Blocks.AIR.getDefaultState();
} }
} }

View file

@ -3,9 +3,9 @@
"parent": "block/block", "parent": "block/block",
"textures": { "textures": {
"4": "create:block/copper_gearbox", "4": "create:block/copper_gearbox",
"8": "create:block/oxidized/copper_block_0", "8": "create:block/copper_plating",
"9": "create:block/fluid_pipe", "9": "create:block/fluid_pipe",
"particle": "create:block/oxidized/copper_block_0" "particle": "create:block/copper_plating"
}, },
"elements": [ "elements": [
{ {

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
{"meta":{"format_version":"3.2","model_format":"java_block","box_uv":false},"name":"rope","parent":"block/block","ambientocclusion":true,"front_gui_light":false,"resolution":{"width":16,"height":16},"elements":[{"name":"rope","from":[6,0,6],"to":[10,16,10],"autouv":0,"color":6,"locked":false,"origin":[7.75,0,8],"faces":{"north":{"uv":[0,0,4,16],"texture":0},"east":{"uv":[0,0,4,16],"texture":0},"south":{"uv":[0,0,4,16],"texture":0},"west":{"uv":[0,0,4,16],"texture":0},"up":{"uv":[0,0,4,4],"rotation":90,"texture":0},"down":{"uv":[0,0,4,4],"texture":0}},"uuid":"3f245b42-dde8-d34f-9f25-ae6eb2f322ae"}],"outliner":["3f245b42-dde8-d34f-9f25-ae6eb2f322ae"],"textures":[{"path":"C:\\Users\\krypp\\Documents\\Pixel Art\\Create Mod\\Pulley Pump\\copper_pulley_rope.png","name":"copper_pulley_rope.png","folder":"Pulley Pump","namespace":"create","id":"5","particle":true,"mode":"bitmap","saved":true,"uuid":"8ffc2f62-b5b6-1af9-ecc1-e22a9ae075aa","source":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAX0lEQVQ4T2M00tP4z8fLwfDp8w+GX7//MLCxsjCQwmfU0VT5r6IgwfDh0xe4IaTwGUddwEB5GLS1tf2Xl5dn0NDQYLhx4wbDw4cPGUjhMy5duvQ/uZpBlo2mgz/DIQwAKD7WmGK5ZIUAAAAASUVORK5CYII="}]}

View file

@ -7,9 +7,9 @@
"4": "create:block/copper_gearbox", "4": "create:block/copper_gearbox",
"5": "create:block/hose_pulley_rope", "5": "create:block/hose_pulley_rope",
"6": "create:block/hose_pulley_magnet", "6": "create:block/hose_pulley_magnet",
"8": "create:block/oxidized/copper_block_0", "8": "create:block/copper_plating",
"9": "create:block/fluid_pipe", "9": "create:block/fluid_pipe",
"particle": "create:block/oxidized/copper_block_0" "particle": "create:block/copper_plating"
}, },
"elements": [ "elements": [
{ {

View file

@ -0,0 +1,8 @@
{
"parent": "create:block/portable_storage_interface/block",
"textures": {
"0": "create:block/portable_fluid_interface",
"1": "create:block/copper_casing",
"particle": "create:block/copper_casing"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "create:block/portable_storage_interface/block_middle",
"textures": {
"0": "create:block/portable_fluid_interface"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "create:block/portable_storage_interface/block_middle_powered",
"textures": {
"0": "create:block/portable_fluid_interface"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "create:block/portable_storage_interface/block_top",
"textures": {
"0": "create:block/portable_fluid_interface"
}
}

View file

@ -0,0 +1,7 @@
{
"parent": "create:block/portable_storage_interface/item",
"textures": {
"0": "create:block/portable_fluid_interface",
"1": "create:block/copper_casing"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 432 B

View file

@ -3,7 +3,7 @@
"parent": "block/block", "parent": "block/block",
"textures": { "textures": {
"0": "create:block/spout", "0": "create:block/spout",
"particle": "create:block/oxidized/copper_block_0" "particle": "create:block/copper_plating"
}, },
"elements": [ "elements": [
{ {

View file

@ -3,7 +3,7 @@
"parent": "block/block", "parent": "block/block",
"textures": { "textures": {
"0": "create:block/spout", "0": "create:block/spout",
"particle": "create:block/oxidized/copper_block_0" "particle": "create:block/copper_plating"
}, },
"elements": [ "elements": [
{ {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 516 B

After

Width:  |  Height:  |  Size: 867 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 394 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 552 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 552 B

After

Width:  |  Height:  |  Size: 389 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 295 B

After

Width:  |  Height:  |  Size: 373 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 625 B

After

Width:  |  Height:  |  Size: 398 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 822 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 432 B

After

Width:  |  Height:  |  Size: 495 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 642 B

After

Width:  |  Height:  |  Size: 324 B