mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-01-18 17:07:52 +01:00
Merge pull request #1 from Creators-of-Create/mc1.15/dev
sync 1.15/dev progress
This commit is contained in:
commit
bb21a5f96d
216 changed files with 5856 additions and 2024 deletions
|
@ -41,7 +41,7 @@ e81608346d43406ee72cae0f78b8bcfb37ba2d75 assets/create/blockstates/brown_seat.js
|
|||
2ca82a3c4bf7ba1a9cf3bb674e786d9b23b020a4 assets/create/blockstates/chiseled_limestone.json
|
||||
cbcdab42d01f8085db9e5f8db884f8adf7f17625 assets/create/blockstates/chiseled_scoria.json
|
||||
291952556c52fba2af5bbd793c71af81abd27e71 assets/create/blockstates/chiseled_weathered_limestone.json
|
||||
99def0a786714a337e2b1b17db844e4d1aee6234 assets/create/blockstates/chute.json
|
||||
b59324f051f21d8ce1a48a08f4721a61a3c414d6 assets/create/blockstates/chute.json
|
||||
4947c261310445fa55b92038326ac82967d192dd assets/create/blockstates/clockwork_bearing.json
|
||||
1f33834c685e3243882acfe20183fe64dfa872be assets/create/blockstates/clutch.json
|
||||
e5e3757e99c139d67b2a70288466d8a74d818841 assets/create/blockstates/cogwheel.json
|
||||
|
@ -91,6 +91,7 @@ f63a5816d4bfe643aa098d03c3b54462dd06fe19 assets/create/blockstates/dolomite_cobb
|
|||
f179202e59e449157f89efc37229b03bbfd391d7 assets/create/blockstates/dolomite_pillar.json
|
||||
7b1c40891b07c8f3238537625d9e25c8627e7333 assets/create/blockstates/encased_belt.json
|
||||
7b2b836649e729feafa60972bf95e3afb2143131 assets/create/blockstates/encased_fan.json
|
||||
656813b75dd3b901bf34f24df785e4b0fbe11aa6 assets/create/blockstates/encased_fluid_pipe.json
|
||||
e157d7f67b08493b71d7ffea8d622f4a64dbc155 assets/create/blockstates/encased_shaft.json
|
||||
1442ff1a0e404f99263ba99d734da1dfed03d4e3 assets/create/blockstates/extractor.json
|
||||
a774e815376a67e2a2de44e39af0a1a0b4406932 assets/create/blockstates/fancy_andesite_bricks.json
|
||||
|
@ -129,7 +130,7 @@ de8a40b7daf1497d5aecee47a43b3e0b1d030b00 assets/create/blockstates/fancy_scoria_
|
|||
fc9ac0a7e7191b93516719455a17177fa6524ecc assets/create/blockstates/fancy_weathered_limestone_bricks_slab.json
|
||||
b2a7c321b1795f20e7433f81a55ce4683de081b8 assets/create/blockstates/fancy_weathered_limestone_bricks_stairs.json
|
||||
6372fe02ba0065acb0758121c45a15a1a8fdc5de assets/create/blockstates/fancy_weathered_limestone_bricks_wall.json
|
||||
3d97226b5e8d8f70ed08e45e78db1faf78d5e28b assets/create/blockstates/fluid_pipe.json
|
||||
fe9169716dd21a81a3710a89f0a9b7ea4dcd4d51 assets/create/blockstates/fluid_pipe.json
|
||||
f0eaab18e16c4f3f65ebf3b55b08f0dc445720fe assets/create/blockstates/fluid_tank.json
|
||||
e9da1794b6ece7f9aa8bcb43d42c23a55446133b assets/create/blockstates/flywheel.json
|
||||
ac00d40e1ef50a37041c0481afa1a23a14dea78e assets/create/blockstates/framed_glass.json
|
||||
|
@ -147,6 +148,7 @@ a64d8d0924c0b5b192f355343dd9b3a440875f6a assets/create/blockstates/gabbro_cobble
|
|||
a6b44e8a1c4ce0c7442b2384b41ad36dd133f19b assets/create/blockstates/gabbro_pillar.json
|
||||
9c48e311be8b959bfb98e16ffaa358210ac8b9dd assets/create/blockstates/gearbox.json
|
||||
f34814b17cde3231a1dfb271f3dabf8d6de4fbf6 assets/create/blockstates/gearshift.json
|
||||
93f8bdc22d9a5e04268964e35e4285c8cbf2b89d assets/create/blockstates/glass_fluid_pipe.json
|
||||
87661d61e1645ef5ad4ea34f1c0fa31f139ea431 assets/create/blockstates/granite_bricks.json
|
||||
d7f4cf7be7e9a3895840d9288245c52cbe25f0bd assets/create/blockstates/granite_bricks_slab.json
|
||||
ec51efc72eb6b16c5f99399b4cb6284665d5be99 assets/create/blockstates/granite_bricks_stairs.json
|
||||
|
@ -357,17 +359,17 @@ c77b46d8b459e5c7cc495393546f3fcca8a1fa1d assets/create/blockstates/weathered_lim
|
|||
a3a11524cd3515fc01d905767b4b7ea782adaf03 assets/create/blockstates/yellow_seat.json
|
||||
7f39521b211441f5c3e06d60c5978cebe16cacfb assets/create/blockstates/zinc_block.json
|
||||
b7181bcd8182b2f17088e5aa881f374c9c65470c assets/create/blockstates/zinc_ore.json
|
||||
a9bcfd546e95865633a97e4b29e39c4aec940338 assets/create/lang/en_ud.json
|
||||
aa14daef8d31ca69ace4e643ffdc5cc9aba22818 assets/create/lang/en_us.json
|
||||
b4435a02a94ae72032f3ffb8f9282e41b1dca953 assets/create/lang/unfinished/de_de.json
|
||||
4f9cc39db1e0de14e9aeabea93676b8fa8ba58ec assets/create/lang/unfinished/fr_fr.json
|
||||
a5a1d2d2e6154c07be187dfe2e33c203db1dd678 assets/create/lang/unfinished/it_it.json
|
||||
022fee71a855d3cd206c2c1d5c36c38f089f8120 assets/create/lang/unfinished/ja_jp.json
|
||||
07da262b3005fd53abd22b5da558e3494bbefa90 assets/create/lang/unfinished/ko_kr.json
|
||||
f1a7c021d2a48a56141ffe70ddec7128c5ad7261 assets/create/lang/unfinished/nl_nl.json
|
||||
5e10814eb0606a6bd20097067394a93842ef7957 assets/create/lang/unfinished/pt_br.json
|
||||
f1367be00730002ee0f233dfebb5e920eed56900 assets/create/lang/unfinished/ru_ru.json
|
||||
76928b7d9f7f41f4fa622824a872bec8e5635cea assets/create/lang/unfinished/zh_cn.json
|
||||
15f8e8f779c6ce41a9e42d87796df14d1415ab5a assets/create/lang/en_ud.json
|
||||
3c6d8906ded9a78050003f8b029407ef2078da87 assets/create/lang/en_us.json
|
||||
1abcbe5404e82eb9b944c9075eb39ff3b20512e5 assets/create/lang/unfinished/de_de.json
|
||||
e9f885ab2cee12075ec10a85e95e2f0a7fc49d9b assets/create/lang/unfinished/fr_fr.json
|
||||
44331773068529facc64870b0762609567fec8b6 assets/create/lang/unfinished/it_it.json
|
||||
e3c2ef988da795fc84ea8a9bff8b8557ac6c370a assets/create/lang/unfinished/ja_jp.json
|
||||
a5c17249f0b2575c372c658bfd958fe4244fb5d6 assets/create/lang/unfinished/ko_kr.json
|
||||
abcfc0ab1bf1b077f0aeaf54e00c2aceef78d253 assets/create/lang/unfinished/nl_nl.json
|
||||
899ebaa95bf6d3140bf6bbcf6f8a5fab2ab5111e assets/create/lang/unfinished/pt_br.json
|
||||
bba218b9d488faf4406d975eba81996f621b2200 assets/create/lang/unfinished/ru_ru.json
|
||||
b87385232b0be35079736a3a32ff88f252721cf3 assets/create/lang/unfinished/zh_cn.json
|
||||
846200eb548d3bfa2e77b41039de159b4b6cfb45 assets/create/models/block/acacia_window.json
|
||||
1930fa3a3c98d53dd19e4ee7f55bc27fd47aa281 assets/create/models/block/acacia_window_pane_noside.json
|
||||
1763ea2c9b981d187f5031ba608f3d5d3be3986a assets/create/models/block/acacia_window_pane_noside_alt.json
|
||||
|
@ -544,6 +546,7 @@ cc6d9300cd26f2323c653dbcc61b7a885be8fa3b assets/create/models/block/dolomite_cob
|
|||
a101974d906487326dc38916f828d12a278a49ae assets/create/models/block/dolomite_cobblestone_wall_post.json
|
||||
9c497140dfe73abe1964479eaf1af8f1892de290 assets/create/models/block/dolomite_cobblestone_wall_side.json
|
||||
999a7cd79a9dc80c47fd6103b65f006b55187402 assets/create/models/block/dolomite_pillar.json
|
||||
1a8bac1e97a2a6c3cc362081568d2a7fce815ad5 assets/create/models/block/encased_fluid_pipe.json
|
||||
17dae5fdc1a551d8ab1ab8a68cabf7a8c3848d86 assets/create/models/block/fancy_andesite_bricks.json
|
||||
cfb2cd84a1cbd9226a77ebc1f6c29e8eaa9c577f assets/create/models/block/fancy_andesite_bricks_slab.json
|
||||
8ee27601996ab577991b6a0f7e9df27db0282cad assets/create/models/block/fancy_andesite_bricks_slab_top.json
|
||||
|
@ -1441,6 +1444,14 @@ a135eec618e448f440d9f42cc7a3e6c63fc45a71 data/create/advancements/overstressed.j
|
|||
1e3cd82e36fd4bcd053d652a0eead4458ed7f315 data/create/advancements/press.json
|
||||
b2782692d27ffb105e3167174cebe1ebdd4a9867 data/create/advancements/recipes/create.base/brass_block.json
|
||||
df6f220e693f5256bb3df8d6c7769bc931820ae5 data/create/advancements/recipes/create.base/copper_block.json
|
||||
dbe67196168805a5903aa29de7631d33329060d1 data/create/advancements/recipes/create.base/crafting_shaped/schematics/schematic_table.json
|
||||
0c5badff77b751b086b0da5943bea186256668cb data/create/advancements/recipes/create.base/crafting_shaped/schematics/schematicannon.json
|
||||
c2ff86e360002e714877060540378940b8d72c4b data/create/advancements/recipes/create.base/crafting_shapeless/appliances/dough.json
|
||||
b77cfa58f80d92299ea628b361bd42d462517d13 data/create/advancements/recipes/create.base/crafting_shapeless/materials/red_sand_paper.json
|
||||
cbbd15261cbb270237347cf00246a6b4045e5ce0 data/create/advancements/recipes/create.base/crafting_shapeless/materials/rose_quartz.json
|
||||
aaea2ee62bb7888e83fcc282c87bc6cb970d30ec data/create/advancements/recipes/create.base/crafting_shapeless/materials/sand_paper.json
|
||||
f6b8aa96169d3857c31d8a087ca1dd6b5077defc data/create/advancements/recipes/create.base/crafting_shapeless/schematics/empty_schematic.json
|
||||
e53989fa8a2742b55226e4af040ae3a98cc07994 data/create/advancements/recipes/create.base/crafting_shapeless/schematics/schematic_and_quill.json
|
||||
82280c50b78dd7e8c179cb8e8f0c074b26ec9586 data/create/advancements/recipes/create.base/zinc_block.json
|
||||
909345eb2f5541a2be592a52800319a8765ca345 data/create/advancements/recipes/create.palettes/acacia_window.json
|
||||
73f99cd857b056da5e19ff8304a4f5eeacc4f8cd data/create/advancements/recipes/create.palettes/acacia_window_pane.json
|
||||
|
@ -1815,6 +1826,8 @@ b77c5aecd0b6dd37a0c69431ab7a4a40fe0770eb data/create/advancements/recipes/create
|
|||
e548127075559307b767b802f4809ed52eedd543 data/create/advancements/recipes/create.palettes/weathered_limestone_cobblestone_wall_from_weathered_limestone_cobblestone_stonecutting.json
|
||||
23ba836640a4d543db6f1cb72cc86a6543fe2fbe data/create/advancements/recipes/create.palettes/weathered_limestone_pillar.json
|
||||
9790a16fd56e47cb5abbfad4062672303c224d9f data/create/advancements/recipes/create.palettes/weathered_limestone_pillar_from_weathered_limestone_stonecutting.json
|
||||
731da8361ecf00e2280a269e15cee00195d70bd7 data/create/advancements/recipes/food/crafting_shaped/appliances/cake.json
|
||||
fc2411c0f4a4da43f6f213fc3bfffd35e6ad3775 data/create/advancements/recipes/misc/crafting_shapeless/appliances/slime_ball.json
|
||||
e0b9edc5e59647e7dd99be17369b263dadf407d4 data/create/advancements/refined_radiance.json
|
||||
fc12b590ab8f5ac901db21c67ba3850f157e1421 data/create/advancements/root.json
|
||||
8529fc7919b6a3240ede2bb8043906bb72fb7f9e data/create/advancements/shadow_end.json
|
||||
|
@ -1920,6 +1933,7 @@ d5fc5b3dc612cd748117e9d8b0ecda76e73f4514 data/create/loot_tables/blocks/dolomite
|
|||
6121c99e6e037dda9022af3a414aee444467ac1b data/create/loot_tables/blocks/dolomite_pillar.json
|
||||
503a93787537b46f462d32b0382c3396f42bb1f6 data/create/loot_tables/blocks/encased_belt.json
|
||||
9055d82b983b673e1638d17b712b9fcd1f5a52e6 data/create/loot_tables/blocks/encased_fan.json
|
||||
c8aa9bbed8fd703eb1853de0b7c9e04dffb7a511 data/create/loot_tables/blocks/encased_fluid_pipe.json
|
||||
b127cb6920e6d7d9c8b2402cb186402a9a8dd3fc data/create/loot_tables/blocks/encased_shaft.json
|
||||
5a47c1535c866184b4ffca65763f5676f319e0aa data/create/loot_tables/blocks/extractor.json
|
||||
ddfc4764a6039d771e03af815ac4493da80d2e6b data/create/loot_tables/blocks/fancy_andesite_bricks.json
|
||||
|
@ -1976,6 +1990,7 @@ ae19749df10663efc51b8b27af310164f250ed38 data/create/loot_tables/blocks/gabbro_c
|
|||
e8d09c919e3b8125d7da0f38383c01bcfc61c7a8 data/create/loot_tables/blocks/gabbro_pillar.json
|
||||
b0109b4a4f0f738cbbe6b5911e8c3c0310b76f99 data/create/loot_tables/blocks/gearbox.json
|
||||
5f39461c5c9d3ad8d84195b06b9468fe2b0fb269 data/create/loot_tables/blocks/gearshift.json
|
||||
c8aa9bbed8fd703eb1853de0b7c9e04dffb7a511 data/create/loot_tables/blocks/glass_fluid_pipe.json
|
||||
74371bc2b516ad9742ca081d82dc1b7f642e25b4 data/create/loot_tables/blocks/granite_bricks.json
|
||||
29f2cbc04f898bb8ff48055a7e43ded85e635bf9 data/create/loot_tables/blocks/granite_bricks_slab.json
|
||||
6b2c74992f261df4f539ff65919e2f4a58b146ec data/create/loot_tables/blocks/granite_bricks_stairs.json
|
||||
|
@ -2214,6 +2229,16 @@ c323b106e88b7de77fea71ff12494abdbb818d15 data/create/recipes/chiseled_limestone_
|
|||
da9a919b476954c1de34826aa7706bf6056a8f12 data/create/recipes/chiseled_scoria_from_scoria_stonecutting.json
|
||||
09faa4ddcf9f3907dcdb3ab3e8b68c1deb2486e5 data/create/recipes/chiseled_weathered_limestone_from_weathered_limestone_stonecutting.json
|
||||
386c52f0aad6e2239f31dc85f7e745b47230846b data/create/recipes/copper_block.json
|
||||
d19b3fa4bedacedf0c57aecba5a7e025e5a6b032 data/create/recipes/crafting_shaped/appliances/cake.json
|
||||
5a7ee5951c15db03a4e38f5cbc1833f3d889e2b1 data/create/recipes/crafting_shaped/schematics/schematic_table.json
|
||||
50cffa44fb016b856629538cb0be52c162139ec5 data/create/recipes/crafting_shaped/schematics/schematicannon.json
|
||||
19526da3a59fc136654ff1bc93c0251581f397a9 data/create/recipes/crafting_shapeless/appliances/dough.json
|
||||
7b5f863dda3d05a79cb85943a178eba0bd8a7dc7 data/create/recipes/crafting_shapeless/appliances/slime_ball.json
|
||||
9c9e40ffd41ce46c65113080a92ff9b4f27e5fab data/create/recipes/crafting_shapeless/materials/red_sand_paper.json
|
||||
7eb292bc564de70227f4bf947050bcdbfc5a8d67 data/create/recipes/crafting_shapeless/materials/rose_quartz.json
|
||||
5ca47ec1bca9a5ce28aabd9868b74b71c829ca07 data/create/recipes/crafting_shapeless/materials/sand_paper.json
|
||||
0b7acc249bed992387aa9702a2c05836ecf584df data/create/recipes/crafting_shapeless/schematics/empty_schematic.json
|
||||
5c47ac2e2b596439a684126fef7265f13de2379b data/create/recipes/crafting_shapeless/schematics/schematic_and_quill.json
|
||||
f2c317e03ac4d42fb631e1625607061e10c480fe data/create/recipes/dark_oak_window.json
|
||||
d9dbae6e237eb38e53a619a0f1b339fca7c59b4d data/create/recipes/dark_oak_window_pane.json
|
||||
55596a590962e3ddd40949917661f0bd94408274 data/create/recipes/dark_scoria_bricks_from_dark_scoria_stonecutting.json
|
||||
|
|
|
@ -1,39 +1,39 @@
|
|||
{
|
||||
"variants": {
|
||||
"facing=down,shape=start": {
|
||||
"model": "create:block/chute/block_windowed"
|
||||
"facing=down,shape=intersection": {
|
||||
"model": "create:block/chute/block_intersection"
|
||||
},
|
||||
"facing=north,shape=start": {
|
||||
"model": "create:block/chute/block_diagonal_start",
|
||||
"facing=north,shape=intersection": {
|
||||
"model": "create:block/chute/block_diagonal_intersection",
|
||||
"y": 180
|
||||
},
|
||||
"facing=south,shape=start": {
|
||||
"model": "create:block/chute/block_diagonal_start"
|
||||
"facing=south,shape=intersection": {
|
||||
"model": "create:block/chute/block_diagonal_intersection"
|
||||
},
|
||||
"facing=west,shape=start": {
|
||||
"model": "create:block/chute/block_diagonal_start",
|
||||
"facing=west,shape=intersection": {
|
||||
"model": "create:block/chute/block_diagonal_intersection",
|
||||
"y": 90
|
||||
},
|
||||
"facing=east,shape=start": {
|
||||
"model": "create:block/chute/block_diagonal_start",
|
||||
"facing=east,shape=intersection": {
|
||||
"model": "create:block/chute/block_diagonal_intersection",
|
||||
"y": 270
|
||||
},
|
||||
"facing=down,shape=window_straight": {
|
||||
"facing=down,shape=window": {
|
||||
"model": "create:block/chute/block_windowed"
|
||||
},
|
||||
"facing=north,shape=window_straight": {
|
||||
"model": "create:block/chute/block_diagonal_straight",
|
||||
"facing=north,shape=window": {
|
||||
"model": "create:block/chute/block_diagonal",
|
||||
"y": 180
|
||||
},
|
||||
"facing=south,shape=window_straight": {
|
||||
"model": "create:block/chute/block_diagonal_straight"
|
||||
"facing=south,shape=window": {
|
||||
"model": "create:block/chute/block_diagonal"
|
||||
},
|
||||
"facing=west,shape=window_straight": {
|
||||
"model": "create:block/chute/block_diagonal_straight",
|
||||
"facing=west,shape=window": {
|
||||
"model": "create:block/chute/block_diagonal",
|
||||
"y": 90
|
||||
},
|
||||
"facing=east,shape=window_straight": {
|
||||
"model": "create:block/chute/block_diagonal_straight",
|
||||
"facing=east,shape=window": {
|
||||
"model": "create:block/chute/block_diagonal",
|
||||
"y": 270
|
||||
},
|
||||
"facing=down,shape=normal": {
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"variants": {
|
||||
"axis=x": {
|
||||
"model": "create:block/encased_fluid_pipe",
|
||||
"x": 90,
|
||||
"y": 90
|
||||
},
|
||||
"axis=y": {
|
||||
"model": "create:block/encased_fluid_pipe"
|
||||
},
|
||||
"axis=z": {
|
||||
"model": "create:block/encased_fluid_pipe",
|
||||
"x": 90,
|
||||
"y": 180
|
||||
}
|
||||
}
|
||||
}
|
|
@ -303,8 +303,8 @@
|
|||
{
|
||||
"when": {
|
||||
"west": "false",
|
||||
"down": "false",
|
||||
"east": "true",
|
||||
"down": "false",
|
||||
"up": "true"
|
||||
},
|
||||
"apply": {
|
||||
|
@ -314,8 +314,8 @@
|
|||
{
|
||||
"when": {
|
||||
"west": "true",
|
||||
"down": "false",
|
||||
"east": "false",
|
||||
"down": "false",
|
||||
"up": "true"
|
||||
},
|
||||
"apply": {
|
||||
|
@ -325,8 +325,8 @@
|
|||
{
|
||||
"when": {
|
||||
"west": "false",
|
||||
"down": "true",
|
||||
"east": "true",
|
||||
"down": "true",
|
||||
"up": "false"
|
||||
},
|
||||
"apply": {
|
||||
|
@ -336,8 +336,8 @@
|
|||
{
|
||||
"when": {
|
||||
"west": "true",
|
||||
"down": "true",
|
||||
"east": "false",
|
||||
"down": "true",
|
||||
"up": "false"
|
||||
},
|
||||
"apply": {
|
||||
|
@ -347,8 +347,8 @@
|
|||
{
|
||||
"when": {
|
||||
"west": "false",
|
||||
"down": "true",
|
||||
"east": "false",
|
||||
"down": "true",
|
||||
"up": "true"
|
||||
},
|
||||
"apply": {
|
||||
|
@ -358,8 +358,8 @@
|
|||
{
|
||||
"when": {
|
||||
"west": "false",
|
||||
"down": "false",
|
||||
"east": "false",
|
||||
"down": "false",
|
||||
"up": "true"
|
||||
},
|
||||
"apply": {
|
||||
|
@ -369,8 +369,8 @@
|
|||
{
|
||||
"when": {
|
||||
"west": "false",
|
||||
"down": "true",
|
||||
"east": "false",
|
||||
"down": "true",
|
||||
"up": "false"
|
||||
},
|
||||
"apply": {
|
||||
|
@ -380,8 +380,8 @@
|
|||
{
|
||||
"when": {
|
||||
"west": "true",
|
||||
"down": "false",
|
||||
"east": "true",
|
||||
"down": "false",
|
||||
"up": "false"
|
||||
},
|
||||
"apply": {
|
||||
|
@ -391,8 +391,8 @@
|
|||
{
|
||||
"when": {
|
||||
"west": "false",
|
||||
"down": "false",
|
||||
"east": "true",
|
||||
"down": "false",
|
||||
"up": "false"
|
||||
},
|
||||
"apply": {
|
||||
|
@ -402,8 +402,8 @@
|
|||
{
|
||||
"when": {
|
||||
"west": "true",
|
||||
"down": "false",
|
||||
"east": "false",
|
||||
"down": "false",
|
||||
"up": "false"
|
||||
},
|
||||
"apply": {
|
||||
|
@ -413,8 +413,8 @@
|
|||
{
|
||||
"when": {
|
||||
"west": "false",
|
||||
"down": "false",
|
||||
"east": "false",
|
||||
"down": "false",
|
||||
"up": "false"
|
||||
},
|
||||
"apply": {
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"variants": {
|
||||
"alt=false,axis=x": {
|
||||
"model": "create:block/fluid_pipe/window",
|
||||
"x": 90,
|
||||
"y": 90
|
||||
},
|
||||
"alt=true,axis=x": {
|
||||
"model": "create:block/fluid_pipe/window_alt",
|
||||
"x": 90,
|
||||
"y": 90
|
||||
},
|
||||
"alt=false,axis=y": {
|
||||
"model": "create:block/fluid_pipe/window"
|
||||
},
|
||||
"alt=true,axis=y": {
|
||||
"model": "create:block/fluid_pipe/window_alt"
|
||||
},
|
||||
"alt=false,axis=z": {
|
||||
"model": "create:block/fluid_pipe/window",
|
||||
"x": 90,
|
||||
"y": 180
|
||||
},
|
||||
"alt=true,axis=z": {
|
||||
"model": "create:block/fluid_pipe/window_alt",
|
||||
"x": 90,
|
||||
"y": 180
|
||||
}
|
||||
}
|
||||
}
|
|
@ -92,6 +92,7 @@
|
|||
"block.create.dolomite_pillar": "\u0279\u0250\u05DF\u05DF\u0131\u0500 \u01DD\u0287\u0131\u026Fo\u05DFo\u15E1",
|
||||
"block.create.encased_belt": "\u0287\u05DF\u01DD\u15FA p\u01DDs\u0250\u0254u\u018E",
|
||||
"block.create.encased_fan": "u\u0250\u2132 p\u01DDs\u0250\u0254u\u018E",
|
||||
"block.create.encased_fluid_pipe": "\u01DDd\u0131\u0500 p\u0131n\u05DF\u2132 p\u01DDs\u0250\u0254u\u018E",
|
||||
"block.create.encased_shaft": "\u0287\u025F\u0250\u0265S p\u01DDs\u0250\u0254u\u018E",
|
||||
"block.create.extractor": "\u0279o\u0287\u0254\u0250\u0279\u0287x\u018E",
|
||||
"block.create.fancy_andesite_bricks": "s\u029E\u0254\u0131\u0279\u15FA \u01DD\u0287\u0131s\u01DDpu\u2C6F \u028E\u0254u\u0250\u2132",
|
||||
|
@ -148,6 +149,7 @@
|
|||
"block.create.gabbro_pillar": "\u0279\u0250\u05DF\u05DF\u0131\u0500 o\u0279qq\u0250\u2141",
|
||||
"block.create.gearbox": "xoq\u0279\u0250\u01DD\u2141",
|
||||
"block.create.gearshift": "\u0287\u025F\u0131\u0265s\u0279\u0250\u01DD\u2141",
|
||||
"block.create.glass_fluid_pipe": "\u01DDd\u0131\u0500 p\u0131n\u05DF\u2132 ss\u0250\u05DF\u2141",
|
||||
"block.create.granite_bricks": "s\u029E\u0254\u0131\u0279\u15FA \u01DD\u0287\u0131u\u0250\u0279\u2141",
|
||||
"block.create.granite_bricks_slab": "q\u0250\u05DFS s\u029E\u0254\u0131\u0279\u15FA \u01DD\u0287\u0131u\u0250\u0279\u2141",
|
||||
"block.create.granite_bricks_stairs": "s\u0279\u0131\u0250\u0287S s\u029E\u0254\u0131\u0279\u15FA \u01DD\u0287\u0131u\u0250\u0279\u2141",
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
"block.create.dolomite_pillar": "Dolomite Pillar",
|
||||
"block.create.encased_belt": "Encased Belt",
|
||||
"block.create.encased_fan": "Encased Fan",
|
||||
"block.create.encased_fluid_pipe": "Encased Fluid Pipe",
|
||||
"block.create.encased_shaft": "Encased Shaft",
|
||||
"block.create.extractor": "Extractor",
|
||||
"block.create.fancy_andesite_bricks": "Fancy Andesite Bricks",
|
||||
|
@ -151,6 +152,7 @@
|
|||
"block.create.gabbro_pillar": "Gabbro Pillar",
|
||||
"block.create.gearbox": "Gearbox",
|
||||
"block.create.gearshift": "Gearshift",
|
||||
"block.create.glass_fluid_pipe": "Glass Fluid Pipe",
|
||||
"block.create.granite_bricks": "Granite Bricks",
|
||||
"block.create.granite_bricks_slab": "Granite Bricks Slab",
|
||||
"block.create.granite_bricks_stairs": "Granite Bricks Stairs",
|
||||
|
@ -462,7 +464,7 @@
|
|||
"advancement.create.electron_tube": "Beep boop",
|
||||
"advancement.create.electron_tube.desc": "Make some Electron Tubes, useful in crafting less primitive machinery.",
|
||||
"advancement.create.mechanical_saw": "Stationary Chopping",
|
||||
"advancement.create.mechanical_saw.desc": "Place and power a Mechanical mechanical_saw",
|
||||
"advancement.create.mechanical_saw.desc": "Place and power a Mechanical Saw",
|
||||
"advancement.create.basin": "Basin Operation",
|
||||
"advancement.create.basin.desc": "Place a basin and try throwing items into it.",
|
||||
"advancement.create.mixer": "Mixin' it Up",
|
||||
|
@ -520,7 +522,7 @@
|
|||
"death.attack.create.fan_fire": "%1$s was burned to death by hot air",
|
||||
"death.attack.create.fan_lava": "%1$s was burned to death by lava fan",
|
||||
"death.attack.create.mechanical_drill": "%1$s was impaled by Mechanical mechanical_drill",
|
||||
"death.attack.create.mechanical_saw": "%1$s got cut in half by Mechanical mechanical_saw",
|
||||
"death.attack.create.mechanical_saw": "%1$s got cut in half by Mechanical Saw",
|
||||
"death.attack.create.cuckoo_clock_explosion": "%1$s was blown up by tampered cuckoo clock",
|
||||
|
||||
"create.block.deployer.damage_source_name": "a rogue Deployer",
|
||||
|
@ -537,7 +539,7 @@
|
|||
"create.recipe.pressing": "Pressing",
|
||||
"create.recipe.mixing": "Mixing",
|
||||
"create.recipe.packing": "Compacting",
|
||||
"create.recipe.mechanical_sawing": "mechanical_sawing",
|
||||
"create.recipe.mechanical_sawing": "Sawing",
|
||||
"create.recipe.mechanical_crafting": "Mechanical Crafting",
|
||||
"create.recipe.block_cutting": "Block Cutting",
|
||||
"create.recipe.blockzapper_upgrade": "Handheld Blockzapper",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 814",
|
||||
"_": "Missing Localizations: 816",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -96,6 +96,7 @@
|
|||
"block.create.dolomite_pillar": "Dolomitsäule",
|
||||
"block.create.encased_belt": "Eingeschlossener Riemen",
|
||||
"block.create.encased_fan": "Eingeschlossener Propeller",
|
||||
"block.create.encased_fluid_pipe": "UNLOCALIZED: Encased Fluid Pipe",
|
||||
"block.create.encased_shaft": "Eingeschlossene Welle",
|
||||
"block.create.extractor": "Auswerfer",
|
||||
"block.create.fancy_andesite_bricks": "UNLOCALIZED: Fancy Andesite Bricks",
|
||||
|
@ -152,6 +153,7 @@
|
|||
"block.create.gabbro_pillar": "UNLOCALIZED: Gabbro Pillar",
|
||||
"block.create.gearbox": "Getriebe",
|
||||
"block.create.gearshift": "Gangschaltung",
|
||||
"block.create.glass_fluid_pipe": "UNLOCALIZED: Glass Fluid Pipe",
|
||||
"block.create.granite_bricks": "Granitziegel",
|
||||
"block.create.granite_bricks_slab": "UNLOCALIZED: Granite Bricks Slab",
|
||||
"block.create.granite_bricks_stairs": "UNLOCALIZED: Granite Bricks Stairs",
|
||||
|
@ -463,7 +465,7 @@
|
|||
"advancement.create.electron_tube": "UNLOCALIZED: Beep boop",
|
||||
"advancement.create.electron_tube.desc": "UNLOCALIZED: Make some Electron Tubes, useful in crafting less primitive machinery.",
|
||||
"advancement.create.mechanical_saw": "UNLOCALIZED: Stationary Chopping",
|
||||
"advancement.create.mechanical_saw.desc": "UNLOCALIZED: Place and power a Mechanical mechanical_saw",
|
||||
"advancement.create.mechanical_saw.desc": "UNLOCALIZED: Place and power a Mechanical Saw",
|
||||
"advancement.create.basin": "UNLOCALIZED: Basin Operation",
|
||||
"advancement.create.basin.desc": "UNLOCALIZED: Place a basin and try throwing items into it.",
|
||||
"advancement.create.mixer": "UNLOCALIZED: Mixin' it Up",
|
||||
|
@ -521,7 +523,7 @@
|
|||
"death.attack.create.fan_fire": "%1$s hat heiße Luft eingeatmet",
|
||||
"death.attack.create.fan_lava": "%1$s wurde von Lava verweht",
|
||||
"death.attack.create.mechanical_drill": "%1$s wurde von einem Bohrer durchlöchert",
|
||||
"death.attack.create.mechanical_saw": "UNLOCALIZED: %1$s got cut in half by Mechanical mechanical_saw",
|
||||
"death.attack.create.mechanical_saw": "UNLOCALIZED: %1$s got cut in half by Mechanical Saw",
|
||||
"death.attack.create.cuckoo_clock_explosion": "UNLOCALIZED: %1$s was blown up by tampered cuckoo clock",
|
||||
|
||||
"create.block.deployer.damage_source_name": "UNLOCALIZED: a rogue Deployer",
|
||||
|
@ -538,7 +540,7 @@
|
|||
"create.recipe.pressing": "Mechanische Presse",
|
||||
"create.recipe.mixing": "UNLOCALIZED: Mixing",
|
||||
"create.recipe.packing": "UNLOCALIZED: Compacting",
|
||||
"create.recipe.mechanical_sawing": "UNLOCALIZED: mechanical_sawing",
|
||||
"create.recipe.mechanical_sawing": "UNLOCALIZED: Sawing",
|
||||
"create.recipe.mechanical_crafting": "UNLOCALIZED: Mechanical Crafting",
|
||||
"create.recipe.block_cutting": "UNLOCALIZED: Block Cutting",
|
||||
"create.recipe.blockzapper_upgrade": "Blockpistole",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 417",
|
||||
"_": "Missing Localizations: 419",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -96,6 +96,7 @@
|
|||
"block.create.dolomite_pillar": "Pillier de dolomie",
|
||||
"block.create.encased_belt": "Tapis roulant enfermé",
|
||||
"block.create.encased_fan": "Ventilateur enfermé",
|
||||
"block.create.encased_fluid_pipe": "UNLOCALIZED: Encased Fluid Pipe",
|
||||
"block.create.encased_shaft": "Arbre mécanique enfermé",
|
||||
"block.create.extractor": "Extracteur",
|
||||
"block.create.fancy_andesite_bricks": "UNLOCALIZED: Fancy Andesite Bricks",
|
||||
|
@ -152,6 +153,7 @@
|
|||
"block.create.gabbro_pillar": "UNLOCALIZED: Gabbro Pillar",
|
||||
"block.create.gearbox": "Boîte à roue dentée",
|
||||
"block.create.gearshift": "Décaleur de rotation",
|
||||
"block.create.glass_fluid_pipe": "UNLOCALIZED: Glass Fluid Pipe",
|
||||
"block.create.granite_bricks": "Briques de granite",
|
||||
"block.create.granite_bricks_slab": "UNLOCALIZED: Granite Bricks Slab",
|
||||
"block.create.granite_bricks_stairs": "UNLOCALIZED: Granite Bricks Stairs",
|
||||
|
@ -463,7 +465,7 @@
|
|||
"advancement.create.electron_tube": "UNLOCALIZED: Beep boop",
|
||||
"advancement.create.electron_tube.desc": "UNLOCALIZED: Make some Electron Tubes, useful in crafting less primitive machinery.",
|
||||
"advancement.create.mechanical_saw": "UNLOCALIZED: Stationary Chopping",
|
||||
"advancement.create.mechanical_saw.desc": "UNLOCALIZED: Place and power a Mechanical mechanical_saw",
|
||||
"advancement.create.mechanical_saw.desc": "UNLOCALIZED: Place and power a Mechanical Saw",
|
||||
"advancement.create.basin": "UNLOCALIZED: Basin Operation",
|
||||
"advancement.create.basin.desc": "UNLOCALIZED: Place a basin and try throwing items into it.",
|
||||
"advancement.create.mixer": "UNLOCALIZED: Mixin' it Up",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 401",
|
||||
"_": "Missing Localizations: 403",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -96,6 +96,7 @@
|
|||
"block.create.dolomite_pillar": "Pilastro di Dolomite",
|
||||
"block.create.encased_belt": "Nastro Incassato",
|
||||
"block.create.encased_fan": "Ventilatore incassato",
|
||||
"block.create.encased_fluid_pipe": "UNLOCALIZED: Encased Fluid Pipe",
|
||||
"block.create.encased_shaft": "Albero Incassato",
|
||||
"block.create.extractor": "Estrattore",
|
||||
"block.create.fancy_andesite_bricks": "UNLOCALIZED: Fancy Andesite Bricks",
|
||||
|
@ -152,6 +153,7 @@
|
|||
"block.create.gabbro_pillar": "UNLOCALIZED: Gabbro Pillar",
|
||||
"block.create.gearbox": "Riduttore",
|
||||
"block.create.gearshift": "Cambio",
|
||||
"block.create.glass_fluid_pipe": "UNLOCALIZED: Glass Fluid Pipe",
|
||||
"block.create.granite_bricks": "Mattoni di Granito",
|
||||
"block.create.granite_bricks_slab": "UNLOCALIZED: Granite Bricks Slab",
|
||||
"block.create.granite_bricks_stairs": "UNLOCALIZED: Granite Bricks Stairs",
|
||||
|
@ -463,7 +465,7 @@
|
|||
"advancement.create.electron_tube": "UNLOCALIZED: Beep boop",
|
||||
"advancement.create.electron_tube.desc": "UNLOCALIZED: Make some Electron Tubes, useful in crafting less primitive machinery.",
|
||||
"advancement.create.mechanical_saw": "UNLOCALIZED: Stationary Chopping",
|
||||
"advancement.create.mechanical_saw.desc": "UNLOCALIZED: Place and power a Mechanical mechanical_saw",
|
||||
"advancement.create.mechanical_saw.desc": "UNLOCALIZED: Place and power a Mechanical Saw",
|
||||
"advancement.create.basin": "UNLOCALIZED: Basin Operation",
|
||||
"advancement.create.basin.desc": "UNLOCALIZED: Place a basin and try throwing items into it.",
|
||||
"advancement.create.mixer": "UNLOCALIZED: Mixin' it Up",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 396",
|
||||
"_": "Missing Localizations: 398",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -96,6 +96,7 @@
|
|||
"block.create.dolomite_pillar": "苦灰石の柱",
|
||||
"block.create.encased_belt": "ケース入りベルト",
|
||||
"block.create.encased_fan": "ケース入りファン",
|
||||
"block.create.encased_fluid_pipe": "UNLOCALIZED: Encased Fluid Pipe",
|
||||
"block.create.encased_shaft": "ケース入りシャフト",
|
||||
"block.create.extractor": "エクストラクター",
|
||||
"block.create.fancy_andesite_bricks": "UNLOCALIZED: Fancy Andesite Bricks",
|
||||
|
@ -152,6 +153,7 @@
|
|||
"block.create.gabbro_pillar": "UNLOCALIZED: Gabbro Pillar",
|
||||
"block.create.gearbox": "ギアボックス",
|
||||
"block.create.gearshift": "ギアシフト",
|
||||
"block.create.glass_fluid_pipe": "UNLOCALIZED: Glass Fluid Pipe",
|
||||
"block.create.granite_bricks": "花崗岩レンガ",
|
||||
"block.create.granite_bricks_slab": "UNLOCALIZED: Granite Bricks Slab",
|
||||
"block.create.granite_bricks_stairs": "UNLOCALIZED: Granite Bricks Stairs",
|
||||
|
@ -463,7 +465,7 @@
|
|||
"advancement.create.electron_tube": "UNLOCALIZED: Beep boop",
|
||||
"advancement.create.electron_tube.desc": "UNLOCALIZED: Make some Electron Tubes, useful in crafting less primitive machinery.",
|
||||
"advancement.create.mechanical_saw": "UNLOCALIZED: Stationary Chopping",
|
||||
"advancement.create.mechanical_saw.desc": "UNLOCALIZED: Place and power a Mechanical mechanical_saw",
|
||||
"advancement.create.mechanical_saw.desc": "UNLOCALIZED: Place and power a Mechanical Saw",
|
||||
"advancement.create.basin": "UNLOCALIZED: Basin Operation",
|
||||
"advancement.create.basin.desc": "UNLOCALIZED: Place a basin and try throwing items into it.",
|
||||
"advancement.create.mixer": "UNLOCALIZED: Mixin' it Up",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 401",
|
||||
"_": "Missing Localizations: 403",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -96,6 +96,7 @@
|
|||
"block.create.dolomite_pillar": "백운암 기둥",
|
||||
"block.create.encased_belt": "덮힌 벨트",
|
||||
"block.create.encased_fan": "덮힌 환풍기",
|
||||
"block.create.encased_fluid_pipe": "UNLOCALIZED: Encased Fluid Pipe",
|
||||
"block.create.encased_shaft": "덮힌 축",
|
||||
"block.create.extractor": "추출기",
|
||||
"block.create.fancy_andesite_bricks": "UNLOCALIZED: Fancy Andesite Bricks",
|
||||
|
@ -152,6 +153,7 @@
|
|||
"block.create.gabbro_pillar": "UNLOCALIZED: Gabbro Pillar",
|
||||
"block.create.gearbox": "기어박스",
|
||||
"block.create.gearshift": "기어쉬프트",
|
||||
"block.create.glass_fluid_pipe": "UNLOCALIZED: Glass Fluid Pipe",
|
||||
"block.create.granite_bricks": "화강암 벽돌",
|
||||
"block.create.granite_bricks_slab": "UNLOCALIZED: Granite Bricks Slab",
|
||||
"block.create.granite_bricks_stairs": "UNLOCALIZED: Granite Bricks Stairs",
|
||||
|
@ -463,7 +465,7 @@
|
|||
"advancement.create.electron_tube": "UNLOCALIZED: Beep boop",
|
||||
"advancement.create.electron_tube.desc": "UNLOCALIZED: Make some Electron Tubes, useful in crafting less primitive machinery.",
|
||||
"advancement.create.mechanical_saw": "UNLOCALIZED: Stationary Chopping",
|
||||
"advancement.create.mechanical_saw.desc": "UNLOCALIZED: Place and power a Mechanical mechanical_saw",
|
||||
"advancement.create.mechanical_saw.desc": "UNLOCALIZED: Place and power a Mechanical Saw",
|
||||
"advancement.create.basin": "UNLOCALIZED: Basin Operation",
|
||||
"advancement.create.basin.desc": "UNLOCALIZED: Place a basin and try throwing items into it.",
|
||||
"advancement.create.mixer": "UNLOCALIZED: Mixin' it Up",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 751",
|
||||
"_": "Missing Localizations: 753",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -96,6 +96,7 @@
|
|||
"block.create.dolomite_pillar": "Dolomiet Pilaar",
|
||||
"block.create.encased_belt": "Omhulsde Transportband",
|
||||
"block.create.encased_fan": "Omhulsde Ventilator",
|
||||
"block.create.encased_fluid_pipe": "UNLOCALIZED: Encased Fluid Pipe",
|
||||
"block.create.encased_shaft": "Omhulsde Drijfas",
|
||||
"block.create.extractor": "Extractor",
|
||||
"block.create.fancy_andesite_bricks": "UNLOCALIZED: Fancy Andesite Bricks",
|
||||
|
@ -152,6 +153,7 @@
|
|||
"block.create.gabbro_pillar": "UNLOCALIZED: Gabbro Pillar",
|
||||
"block.create.gearbox": "Versnellingsbak",
|
||||
"block.create.gearshift": "Versnellingspook",
|
||||
"block.create.glass_fluid_pipe": "UNLOCALIZED: Glass Fluid Pipe",
|
||||
"block.create.granite_bricks": "Granietstenen",
|
||||
"block.create.granite_bricks_slab": "UNLOCALIZED: Granite Bricks Slab",
|
||||
"block.create.granite_bricks_stairs": "UNLOCALIZED: Granite Bricks Stairs",
|
||||
|
@ -463,7 +465,7 @@
|
|||
"advancement.create.electron_tube": "UNLOCALIZED: Beep boop",
|
||||
"advancement.create.electron_tube.desc": "UNLOCALIZED: Make some Electron Tubes, useful in crafting less primitive machinery.",
|
||||
"advancement.create.mechanical_saw": "UNLOCALIZED: Stationary Chopping",
|
||||
"advancement.create.mechanical_saw.desc": "UNLOCALIZED: Place and power a Mechanical mechanical_saw",
|
||||
"advancement.create.mechanical_saw.desc": "UNLOCALIZED: Place and power a Mechanical Saw",
|
||||
"advancement.create.basin": "UNLOCALIZED: Basin Operation",
|
||||
"advancement.create.basin.desc": "UNLOCALIZED: Place a basin and try throwing items into it.",
|
||||
"advancement.create.mixer": "UNLOCALIZED: Mixin' it Up",
|
||||
|
@ -521,7 +523,7 @@
|
|||
"death.attack.create.fan_fire": "%1$s is verbrand door hete lucht",
|
||||
"death.attack.create.fan_lava": "%1$s is verbrand door een lava ventilator",
|
||||
"death.attack.create.mechanical_drill": "%1$s is gespietst door een mechanische boor",
|
||||
"death.attack.create.mechanical_saw": "UNLOCALIZED: %1$s got cut in half by Mechanical mechanical_saw",
|
||||
"death.attack.create.mechanical_saw": "UNLOCALIZED: %1$s got cut in half by Mechanical Saw",
|
||||
"death.attack.create.cuckoo_clock_explosion": "UNLOCALIZED: %1$s was blown up by tampered cuckoo clock",
|
||||
|
||||
"create.block.deployer.damage_source_name": "UNLOCALIZED: a rogue Deployer",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 821",
|
||||
"_": "Missing Localizations: 823",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -96,6 +96,7 @@
|
|||
"block.create.dolomite_pillar": "Pilar de Dolomite",
|
||||
"block.create.encased_belt": "Esteira Revestida",
|
||||
"block.create.encased_fan": "Ventilador Revestida",
|
||||
"block.create.encased_fluid_pipe": "UNLOCALIZED: Encased Fluid Pipe",
|
||||
"block.create.encased_shaft": "Eixo Revestido",
|
||||
"block.create.extractor": "Extrator",
|
||||
"block.create.fancy_andesite_bricks": "UNLOCALIZED: Fancy Andesite Bricks",
|
||||
|
@ -152,6 +153,7 @@
|
|||
"block.create.gabbro_pillar": "UNLOCALIZED: Gabbro Pillar",
|
||||
"block.create.gearbox": "Caixa de Transmissão",
|
||||
"block.create.gearshift": "Câmbio",
|
||||
"block.create.glass_fluid_pipe": "UNLOCALIZED: Glass Fluid Pipe",
|
||||
"block.create.granite_bricks": "Tijolos de Granito",
|
||||
"block.create.granite_bricks_slab": "UNLOCALIZED: Granite Bricks Slab",
|
||||
"block.create.granite_bricks_stairs": "UNLOCALIZED: Granite Bricks Stairs",
|
||||
|
@ -463,7 +465,7 @@
|
|||
"advancement.create.electron_tube": "UNLOCALIZED: Beep boop",
|
||||
"advancement.create.electron_tube.desc": "UNLOCALIZED: Make some Electron Tubes, useful in crafting less primitive machinery.",
|
||||
"advancement.create.mechanical_saw": "UNLOCALIZED: Stationary Chopping",
|
||||
"advancement.create.mechanical_saw.desc": "UNLOCALIZED: Place and power a Mechanical mechanical_saw",
|
||||
"advancement.create.mechanical_saw.desc": "UNLOCALIZED: Place and power a Mechanical Saw",
|
||||
"advancement.create.basin": "UNLOCALIZED: Basin Operation",
|
||||
"advancement.create.basin.desc": "UNLOCALIZED: Place a basin and try throwing items into it.",
|
||||
"advancement.create.mixer": "UNLOCALIZED: Mixin' it Up",
|
||||
|
@ -521,7 +523,7 @@
|
|||
"death.attack.create.fan_fire": "%1$s foi queimado por ar quente",
|
||||
"death.attack.create.fan_lava": "%1$s foi queimado pelo ventilador de lava",
|
||||
"death.attack.create.mechanical_drill": "%1$s foi empalado pela Furadeira Mecânica",
|
||||
"death.attack.create.mechanical_saw": "UNLOCALIZED: %1$s got cut in half by Mechanical mechanical_saw",
|
||||
"death.attack.create.mechanical_saw": "UNLOCALIZED: %1$s got cut in half by Mechanical Saw",
|
||||
"death.attack.create.cuckoo_clock_explosion": "UNLOCALIZED: %1$s was blown up by tampered cuckoo clock",
|
||||
|
||||
"create.block.deployer.damage_source_name": "UNLOCALIZED: a rogue Deployer",
|
||||
|
@ -538,7 +540,7 @@
|
|||
"create.recipe.pressing": "Prensa Mecânica",
|
||||
"create.recipe.mixing": "UNLOCALIZED: Mixing",
|
||||
"create.recipe.packing": "UNLOCALIZED: Compacting",
|
||||
"create.recipe.mechanical_sawing": "UNLOCALIZED: mechanical_sawing",
|
||||
"create.recipe.mechanical_sawing": "UNLOCALIZED: Sawing",
|
||||
"create.recipe.mechanical_crafting": "UNLOCALIZED: Mechanical Crafting",
|
||||
"create.recipe.block_cutting": "UNLOCALIZED: Block Cutting",
|
||||
"create.recipe.blockzapper_upgrade": "Blockzapper Portátil",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 815",
|
||||
"_": "Missing Localizations: 817",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -96,6 +96,7 @@
|
|||
"block.create.dolomite_pillar": "Доломитовая колонна",
|
||||
"block.create.encased_belt": "Ленточный привод",
|
||||
"block.create.encased_fan": "Вентилятор",
|
||||
"block.create.encased_fluid_pipe": "UNLOCALIZED: Encased Fluid Pipe",
|
||||
"block.create.encased_shaft": "Вальный привод",
|
||||
"block.create.extractor": "Экстрактор",
|
||||
"block.create.fancy_andesite_bricks": "UNLOCALIZED: Fancy Andesite Bricks",
|
||||
|
@ -152,6 +153,7 @@
|
|||
"block.create.gabbro_pillar": "UNLOCALIZED: Gabbro Pillar",
|
||||
"block.create.gearbox": "Муфта",
|
||||
"block.create.gearshift": "Реверсивная муфта",
|
||||
"block.create.glass_fluid_pipe": "UNLOCALIZED: Glass Fluid Pipe",
|
||||
"block.create.granite_bricks": "Гранитные кирпичи",
|
||||
"block.create.granite_bricks_slab": "UNLOCALIZED: Granite Bricks Slab",
|
||||
"block.create.granite_bricks_stairs": "UNLOCALIZED: Granite Bricks Stairs",
|
||||
|
@ -463,7 +465,7 @@
|
|||
"advancement.create.electron_tube": "UNLOCALIZED: Beep boop",
|
||||
"advancement.create.electron_tube.desc": "UNLOCALIZED: Make some Electron Tubes, useful in crafting less primitive machinery.",
|
||||
"advancement.create.mechanical_saw": "UNLOCALIZED: Stationary Chopping",
|
||||
"advancement.create.mechanical_saw.desc": "UNLOCALIZED: Place and power a Mechanical mechanical_saw",
|
||||
"advancement.create.mechanical_saw.desc": "UNLOCALIZED: Place and power a Mechanical Saw",
|
||||
"advancement.create.basin": "UNLOCALIZED: Basin Operation",
|
||||
"advancement.create.basin.desc": "UNLOCALIZED: Place a basin and try throwing items into it.",
|
||||
"advancement.create.mixer": "UNLOCALIZED: Mixin' it Up",
|
||||
|
@ -521,7 +523,7 @@
|
|||
"death.attack.create.fan_fire": "%1$s сгорел заживо от горячего воздуха.",
|
||||
"death.attack.create.fan_lava": "%1$s сгорел заживо от лавового вентилятора",
|
||||
"death.attack.create.mechanical_drill": "%1$s был проколот механическим буром",
|
||||
"death.attack.create.mechanical_saw": "UNLOCALIZED: %1$s got cut in half by Mechanical mechanical_saw",
|
||||
"death.attack.create.mechanical_saw": "UNLOCALIZED: %1$s got cut in half by Mechanical Saw",
|
||||
"death.attack.create.cuckoo_clock_explosion": "UNLOCALIZED: %1$s was blown up by tampered cuckoo clock",
|
||||
|
||||
"create.block.deployer.damage_source_name": "UNLOCALIZED: a rogue Deployer",
|
||||
|
@ -538,7 +540,7 @@
|
|||
"create.recipe.pressing": "Механический пресс",
|
||||
"create.recipe.mixing": "UNLOCALIZED: Mixing",
|
||||
"create.recipe.packing": "UNLOCALIZED: Compacting",
|
||||
"create.recipe.mechanical_sawing": "UNLOCALIZED: mechanical_sawing",
|
||||
"create.recipe.mechanical_sawing": "UNLOCALIZED: Sawing",
|
||||
"create.recipe.mechanical_crafting": "UNLOCALIZED: Mechanical Crafting",
|
||||
"create.recipe.block_cutting": "UNLOCALIZED: Block Cutting",
|
||||
"create.recipe.blockzapper_upgrade": "Портативный размещатель блоков",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_": "Missing Localizations: 77",
|
||||
"_": "Missing Localizations: 79",
|
||||
|
||||
"_": "->------------------------] Game Elements [------------------------<-",
|
||||
|
||||
|
@ -96,6 +96,7 @@
|
|||
"block.create.dolomite_pillar": "竖纹白云岩",
|
||||
"block.create.encased_belt": "连携齿轮箱",
|
||||
"block.create.encased_fan": "鼓风机",
|
||||
"block.create.encased_fluid_pipe": "UNLOCALIZED: Encased Fluid Pipe",
|
||||
"block.create.encased_shaft": "齿轮箱",
|
||||
"block.create.extractor": "提取器",
|
||||
"block.create.fancy_andesite_bricks": "方纹安山岩砖",
|
||||
|
@ -152,6 +153,7 @@
|
|||
"block.create.gabbro_pillar": "竖纹辉长岩",
|
||||
"block.create.gearbox": "十字齿轮箱",
|
||||
"block.create.gearshift": "红石齿轮箱",
|
||||
"block.create.glass_fluid_pipe": "UNLOCALIZED: Glass Fluid Pipe",
|
||||
"block.create.granite_bricks": "花岗岩砖",
|
||||
"block.create.granite_bricks_slab": "花岗岩砖台阶",
|
||||
"block.create.granite_bricks_stairs": "花岗岩砖楼梯",
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"parent": "block/cube_column",
|
||||
"textures": {
|
||||
"side": "create:block/copper_casing",
|
||||
"end": "create:block/encased_pipe"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
"parent": "minecraft:recipes/root",
|
||||
"rewards": {
|
||||
"recipes": [
|
||||
"create:crafting_shaped/schematics/schematic_table"
|
||||
]
|
||||
},
|
||||
"criteria": {
|
||||
"has_item": {
|
||||
"trigger": "minecraft:inventory_changed",
|
||||
"conditions": {
|
||||
"items": [
|
||||
{
|
||||
"item": "create:empty_schematic"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"has_the_recipe": {
|
||||
"trigger": "minecraft:recipe_unlocked",
|
||||
"conditions": {
|
||||
"recipe": "create:crafting_shaped/schematics/schematic_table"
|
||||
}
|
||||
}
|
||||
},
|
||||
"requirements": [
|
||||
[
|
||||
"has_item",
|
||||
"has_the_recipe"
|
||||
]
|
||||
]
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
"parent": "minecraft:recipes/root",
|
||||
"rewards": {
|
||||
"recipes": [
|
||||
"create:crafting_shaped/schematics/schematicannon"
|
||||
]
|
||||
},
|
||||
"criteria": {
|
||||
"has_item": {
|
||||
"trigger": "minecraft:inventory_changed",
|
||||
"conditions": {
|
||||
"items": [
|
||||
{
|
||||
"item": "create:empty_schematic"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"has_the_recipe": {
|
||||
"trigger": "minecraft:recipe_unlocked",
|
||||
"conditions": {
|
||||
"recipe": "create:crafting_shaped/schematics/schematicannon"
|
||||
}
|
||||
}
|
||||
},
|
||||
"requirements": [
|
||||
[
|
||||
"has_item",
|
||||
"has_the_recipe"
|
||||
]
|
||||
]
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
"parent": "minecraft:recipes/root",
|
||||
"rewards": {
|
||||
"recipes": [
|
||||
"create:crafting_shapeless/appliances/dough"
|
||||
]
|
||||
},
|
||||
"criteria": {
|
||||
"has_item": {
|
||||
"trigger": "minecraft:inventory_changed",
|
||||
"conditions": {
|
||||
"items": [
|
||||
{
|
||||
"item": "create:wheat_flour"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"has_the_recipe": {
|
||||
"trigger": "minecraft:recipe_unlocked",
|
||||
"conditions": {
|
||||
"recipe": "create:crafting_shapeless/appliances/dough"
|
||||
}
|
||||
}
|
||||
},
|
||||
"requirements": [
|
||||
[
|
||||
"has_item",
|
||||
"has_the_recipe"
|
||||
]
|
||||
]
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
"parent": "minecraft:recipes/root",
|
||||
"rewards": {
|
||||
"recipes": [
|
||||
"create:crafting_shapeless/materials/red_sand_paper"
|
||||
]
|
||||
},
|
||||
"criteria": {
|
||||
"has_item": {
|
||||
"trigger": "minecraft:inventory_changed",
|
||||
"conditions": {
|
||||
"items": [
|
||||
{
|
||||
"item": "minecraft:paper"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"has_the_recipe": {
|
||||
"trigger": "minecraft:recipe_unlocked",
|
||||
"conditions": {
|
||||
"recipe": "create:crafting_shapeless/materials/red_sand_paper"
|
||||
}
|
||||
}
|
||||
},
|
||||
"requirements": [
|
||||
[
|
||||
"has_item",
|
||||
"has_the_recipe"
|
||||
]
|
||||
]
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
"parent": "minecraft:recipes/root",
|
||||
"rewards": {
|
||||
"recipes": [
|
||||
"create:crafting_shapeless/materials/rose_quartz"
|
||||
]
|
||||
},
|
||||
"criteria": {
|
||||
"has_item": {
|
||||
"trigger": "minecraft:inventory_changed",
|
||||
"conditions": {
|
||||
"items": [
|
||||
{
|
||||
"item": "minecraft:redstone"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"has_the_recipe": {
|
||||
"trigger": "minecraft:recipe_unlocked",
|
||||
"conditions": {
|
||||
"recipe": "create:crafting_shapeless/materials/rose_quartz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"requirements": [
|
||||
[
|
||||
"has_item",
|
||||
"has_the_recipe"
|
||||
]
|
||||
]
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
"parent": "minecraft:recipes/root",
|
||||
"rewards": {
|
||||
"recipes": [
|
||||
"create:crafting_shapeless/materials/sand_paper"
|
||||
]
|
||||
},
|
||||
"criteria": {
|
||||
"has_item": {
|
||||
"trigger": "minecraft:inventory_changed",
|
||||
"conditions": {
|
||||
"items": [
|
||||
{
|
||||
"item": "minecraft:paper"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"has_the_recipe": {
|
||||
"trigger": "minecraft:recipe_unlocked",
|
||||
"conditions": {
|
||||
"recipe": "create:crafting_shapeless/materials/sand_paper"
|
||||
}
|
||||
}
|
||||
},
|
||||
"requirements": [
|
||||
[
|
||||
"has_item",
|
||||
"has_the_recipe"
|
||||
]
|
||||
]
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
"parent": "minecraft:recipes/root",
|
||||
"rewards": {
|
||||
"recipes": [
|
||||
"create:crafting_shapeless/schematics/empty_schematic"
|
||||
]
|
||||
},
|
||||
"criteria": {
|
||||
"has_item": {
|
||||
"trigger": "minecraft:inventory_changed",
|
||||
"conditions": {
|
||||
"items": [
|
||||
{
|
||||
"item": "minecraft:paper"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"has_the_recipe": {
|
||||
"trigger": "minecraft:recipe_unlocked",
|
||||
"conditions": {
|
||||
"recipe": "create:crafting_shapeless/schematics/empty_schematic"
|
||||
}
|
||||
}
|
||||
},
|
||||
"requirements": [
|
||||
[
|
||||
"has_item",
|
||||
"has_the_recipe"
|
||||
]
|
||||
]
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
"parent": "minecraft:recipes/root",
|
||||
"rewards": {
|
||||
"recipes": [
|
||||
"create:crafting_shapeless/schematics/schematic_and_quill"
|
||||
]
|
||||
},
|
||||
"criteria": {
|
||||
"has_item": {
|
||||
"trigger": "minecraft:inventory_changed",
|
||||
"conditions": {
|
||||
"items": [
|
||||
{
|
||||
"item": "minecraft:paper"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"has_the_recipe": {
|
||||
"trigger": "minecraft:recipe_unlocked",
|
||||
"conditions": {
|
||||
"recipe": "create:crafting_shapeless/schematics/schematic_and_quill"
|
||||
}
|
||||
}
|
||||
},
|
||||
"requirements": [
|
||||
[
|
||||
"has_item",
|
||||
"has_the_recipe"
|
||||
]
|
||||
]
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
"parent": "minecraft:recipes/root",
|
||||
"rewards": {
|
||||
"recipes": [
|
||||
"create:crafting_shaped/appliances/cake"
|
||||
]
|
||||
},
|
||||
"criteria": {
|
||||
"has_item": {
|
||||
"trigger": "minecraft:inventory_changed",
|
||||
"conditions": {
|
||||
"items": [
|
||||
{
|
||||
"item": "create:dough"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"has_the_recipe": {
|
||||
"trigger": "minecraft:recipe_unlocked",
|
||||
"conditions": {
|
||||
"recipe": "create:crafting_shaped/appliances/cake"
|
||||
}
|
||||
}
|
||||
},
|
||||
"requirements": [
|
||||
[
|
||||
"has_item",
|
||||
"has_the_recipe"
|
||||
]
|
||||
]
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
"parent": "minecraft:recipes/root",
|
||||
"rewards": {
|
||||
"recipes": [
|
||||
"create:crafting_shapeless/appliances/slime_ball"
|
||||
]
|
||||
},
|
||||
"criteria": {
|
||||
"has_item": {
|
||||
"trigger": "minecraft:inventory_changed",
|
||||
"conditions": {
|
||||
"items": [
|
||||
{
|
||||
"item": "create:dough"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"has_the_recipe": {
|
||||
"trigger": "minecraft:recipe_unlocked",
|
||||
"conditions": {
|
||||
"recipe": "create:crafting_shapeless/appliances/slime_ball"
|
||||
}
|
||||
}
|
||||
},
|
||||
"requirements": [
|
||||
[
|
||||
"has_item",
|
||||
"has_the_recipe"
|
||||
]
|
||||
]
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"type": "minecraft:block",
|
||||
"pools": [
|
||||
{
|
||||
"rolls": 1,
|
||||
"entries": [
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "create:fluid_pipe"
|
||||
}
|
||||
],
|
||||
"conditions": [
|
||||
{
|
||||
"condition": "minecraft:survives_explosion"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"type": "minecraft:block",
|
||||
"pools": [
|
||||
{
|
||||
"rolls": 1,
|
||||
"entries": [
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "create:fluid_pipe"
|
||||
}
|
||||
],
|
||||
"conditions": [
|
||||
{
|
||||
"condition": "minecraft:survives_explosion"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"type": "minecraft:crafting_shaped",
|
||||
"pattern": [
|
||||
" . ",
|
||||
"#+#",
|
||||
" - "
|
||||
],
|
||||
"key": {
|
||||
"#": {
|
||||
"item": "minecraft:sugar"
|
||||
},
|
||||
"+": {
|
||||
"tag": "forge:eggs"
|
||||
},
|
||||
".": {
|
||||
"item": "minecraft:milk_bucket"
|
||||
},
|
||||
"-": {
|
||||
"item": "create:dough"
|
||||
}
|
||||
},
|
||||
"result": {
|
||||
"item": "minecraft:cake"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"type": "minecraft:crafting_shaped",
|
||||
"pattern": [
|
||||
"###",
|
||||
" + ",
|
||||
" + "
|
||||
],
|
||||
"key": {
|
||||
"#": {
|
||||
"tag": "minecraft:wooden_slabs"
|
||||
},
|
||||
"+": {
|
||||
"item": "minecraft:smooth_stone"
|
||||
}
|
||||
},
|
||||
"result": {
|
||||
"item": "create:schematic_table"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"type": "minecraft:crafting_shaped",
|
||||
"pattern": [
|
||||
" . ",
|
||||
"#+#",
|
||||
"_-_"
|
||||
],
|
||||
"key": {
|
||||
"#": {
|
||||
"tag": "minecraft:logs"
|
||||
},
|
||||
"+": {
|
||||
"item": "minecraft:dispenser"
|
||||
},
|
||||
".": {
|
||||
"item": "minecraft:cauldron"
|
||||
},
|
||||
"_": {
|
||||
"item": "minecraft:smooth_stone"
|
||||
},
|
||||
"-": {
|
||||
"item": "minecraft:iron_block"
|
||||
}
|
||||
},
|
||||
"result": {
|
||||
"item": "create:schematicannon"
|
||||
}
|
||||
}
|
|
@ -9,7 +9,6 @@
|
|||
}
|
||||
],
|
||||
"result": {
|
||||
"item": "create:dough",
|
||||
"count": 1
|
||||
"item": "create:dough"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"type": "minecraft:crafting_shapeless",
|
||||
"ingredients": [
|
||||
{
|
||||
"item": "create:dough"
|
||||
},
|
||||
{
|
||||
"tag": "forge:dyes/lime"
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"item": "minecraft:slime_ball"
|
||||
}
|
||||
}
|
|
@ -2,14 +2,13 @@
|
|||
"type": "minecraft:crafting_shapeless",
|
||||
"ingredients": [
|
||||
{
|
||||
"tag": "forge:sand/red"
|
||||
"item": "minecraft:paper"
|
||||
},
|
||||
{
|
||||
"item": "minecraft:paper"
|
||||
"tag": "forge:sand/red"
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"item": "create:red_sand_paper",
|
||||
"count": 1
|
||||
"item": "create:red_sand_paper"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
"type": "minecraft:crafting_shapeless",
|
||||
"ingredients": [
|
||||
{
|
||||
"tag": "forge:gems/quartz"
|
||||
},
|
||||
{
|
||||
"tag": "forge:dusts/redstone"
|
||||
},
|
||||
{
|
||||
"tag": "forge:dusts/redstone"
|
||||
},
|
||||
{
|
||||
"tag": "forge:dusts/redstone"
|
||||
},
|
||||
{
|
||||
"tag": "forge:dusts/redstone"
|
||||
},
|
||||
{
|
||||
"tag": "forge:dusts/redstone"
|
||||
},
|
||||
{
|
||||
"tag": "forge:dusts/redstone"
|
||||
},
|
||||
{
|
||||
"tag": "forge:dusts/redstone"
|
||||
},
|
||||
{
|
||||
"tag": "forge:dusts/redstone"
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"item": "create:rose_quartz"
|
||||
}
|
||||
}
|
|
@ -2,14 +2,13 @@
|
|||
"type": "minecraft:crafting_shapeless",
|
||||
"ingredients": [
|
||||
{
|
||||
"tag": "forge:sand/colorless"
|
||||
"item": "minecraft:paper"
|
||||
},
|
||||
{
|
||||
"item": "minecraft:paper"
|
||||
"tag": "forge:sand/colorless"
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"item": "create:sand_paper",
|
||||
"count": 1
|
||||
"item": "create:sand_paper"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"type": "minecraft:crafting_shapeless",
|
||||
"ingredients": [
|
||||
{
|
||||
"item": "minecraft:paper"
|
||||
},
|
||||
{
|
||||
"tag": "forge:dyes/light_blue"
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"item": "create:empty_schematic"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"type": "minecraft:crafting_shapeless",
|
||||
"ingredients": [
|
||||
{
|
||||
"item": "create:empty_schematic"
|
||||
},
|
||||
{
|
||||
"tag": "forge:feathers"
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"item": "create:schematic_and_quill"
|
||||
}
|
||||
}
|
|
@ -9,9 +9,11 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import com.simibubi.create.content.contraptions.fluids.FluidPipeAttachmentBehaviour.AttachmentTypes;
|
||||
import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock.HeatLevel;
|
||||
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
import com.simibubi.create.foundation.utility.MatrixStacker;
|
||||
import com.simibubi.create.foundation.utility.SuperByteBuffer;
|
||||
|
||||
|
@ -30,46 +32,28 @@ public class AllBlockPartials {
|
|||
public static final AllBlockPartials SCHEMATICANNON_CONNECTOR = get("schematicannon/connector"),
|
||||
SCHEMATICANNON_PIPE = get("schematicannon/pipe"),
|
||||
|
||||
SHAFTLESS_COGWHEEL = get("cogwheel_shaftless"),
|
||||
SHAFT_HALF = get("shaft_half"),
|
||||
|
||||
BELT_PULLEY = get("belt_pulley"),
|
||||
BELT_START = get("belt/start"),
|
||||
BELT_MIDDLE = get("belt/middle"),
|
||||
BELT_END = get("belt/end"),
|
||||
BELT_START_BOTTOM = get("belt/start_bottom"),
|
||||
BELT_MIDDLE_BOTTOM = get("belt/middle_bottom"),
|
||||
BELT_END_BOTTOM = get("belt/end_bottom"),
|
||||
BELT_DIAGONAL_START = get("belt/diagonal_start"),
|
||||
BELT_DIAGONAL_MIDDLE = get("belt/diagonal_middle"),
|
||||
SHAFTLESS_COGWHEEL = get("cogwheel_shaftless"), SHAFT_HALF = get("shaft_half"),
|
||||
|
||||
BELT_PULLEY = get("belt_pulley"), BELT_START = get("belt/start"), BELT_MIDDLE = get("belt/middle"),
|
||||
BELT_END = get("belt/end"), BELT_START_BOTTOM = get("belt/start_bottom"),
|
||||
BELT_MIDDLE_BOTTOM = get("belt/middle_bottom"), BELT_END_BOTTOM = get("belt/end_bottom"),
|
||||
BELT_DIAGONAL_START = get("belt/diagonal_start"), BELT_DIAGONAL_MIDDLE = get("belt/diagonal_middle"),
|
||||
BELT_DIAGONAL_END = get("belt/diagonal_end"),
|
||||
|
||||
ENCASED_FAN_INNER = get("encased_fan/propeller"),
|
||||
HAND_CRANK_HANDLE = get("hand_crank/handle"),
|
||||
MECHANICAL_PRESS_HEAD = get("mechanical_press/head"),
|
||||
MECHANICAL_MIXER_POLE = get("mechanical_mixer/pole"),
|
||||
MECHANICAL_MIXER_HEAD = get("mechanical_mixer/head"),
|
||||
MECHANICAL_CRAFTER_LID = get("mechanical_crafter/lid"),
|
||||
ENCASED_FAN_INNER = get("encased_fan/propeller"), HAND_CRANK_HANDLE = get("hand_crank/handle"),
|
||||
MECHANICAL_PRESS_HEAD = get("mechanical_press/head"), MECHANICAL_MIXER_POLE = get("mechanical_mixer/pole"),
|
||||
MECHANICAL_MIXER_HEAD = get("mechanical_mixer/head"), MECHANICAL_CRAFTER_LID = get("mechanical_crafter/lid"),
|
||||
MECHANICAL_CRAFTER_ARROW = get("mechanical_crafter/arrow"),
|
||||
MECHANICAL_CRAFTER_BELT_FRAME = get("mechanical_crafter/belt"),
|
||||
MECHANICAL_CRAFTER_BELT = get("mechanical_crafter/belt_animated"),
|
||||
GAUGE_DIAL = get("gauge/dial"),
|
||||
GAUGE_INDICATOR = get("gauge/indicator"),
|
||||
GAUGE_HEAD_SPEED = get("gauge/speedometer/head"),
|
||||
GAUGE_HEAD_STRESS = get("gauge/stressometer/head"),
|
||||
BEARING_TOP = get("bearing/top"),
|
||||
DRILL_HEAD = get("mechanical_drill/head"),
|
||||
HARVESTER_BLADE = get("mechanical_harvester/blade"),
|
||||
DEPLOYER_POLE = get("deployer/pole"),
|
||||
DEPLOYER_HAND_POINTING = get("deployer/hand_pointing"),
|
||||
DEPLOYER_HAND_PUNCHING = get("deployer/hand_punching"),
|
||||
DEPLOYER_HAND_HOLDING = get("deployer/hand_holding"),
|
||||
ANALOG_LEVER_HANDLE = get("analog_lever/handle"),
|
||||
ANALOG_LEVER_INDICATOR = get("analog_lever/indicator"),
|
||||
BELT_FUNNEL_FLAP = get("belt_funnel/flap"),
|
||||
BELT_TUNNEL_FLAP = get("belt_tunnel/flap"),
|
||||
FLEXPEATER_INDICATOR = get("diodes/indicator"),
|
||||
FLYWHEEL = get("flywheel/wheel"),
|
||||
MECHANICAL_CRAFTER_BELT = get("mechanical_crafter/belt_animated"), GAUGE_DIAL = get("gauge/dial"),
|
||||
GAUGE_INDICATOR = get("gauge/indicator"), GAUGE_HEAD_SPEED = get("gauge/speedometer/head"),
|
||||
GAUGE_HEAD_STRESS = get("gauge/stressometer/head"), BEARING_TOP = get("bearing/top"),
|
||||
DRILL_HEAD = get("mechanical_drill/head"), HARVESTER_BLADE = get("mechanical_harvester/blade"),
|
||||
DEPLOYER_POLE = get("deployer/pole"), DEPLOYER_HAND_POINTING = get("deployer/hand_pointing"),
|
||||
DEPLOYER_HAND_PUNCHING = get("deployer/hand_punching"), DEPLOYER_HAND_HOLDING = get("deployer/hand_holding"),
|
||||
ANALOG_LEVER_HANDLE = get("analog_lever/handle"), ANALOG_LEVER_INDICATOR = get("analog_lever/indicator"),
|
||||
BELT_FUNNEL_FLAP = get("belt_funnel/flap"), BELT_TUNNEL_FLAP = get("belt_tunnel/flap"),
|
||||
FLEXPEATER_INDICATOR = get("diodes/indicator"), FLYWHEEL = get("flywheel/wheel"),
|
||||
FLYWHEEL_UPPER_ROTATING = get("flywheel/upper_rotating_connector"),
|
||||
|
||||
FLYWHEEL_LOWER_ROTATING = get("flywheel/lower_rotating_connector"),
|
||||
|
@ -95,14 +79,14 @@ public class AllBlockPartials {
|
|||
|
||||
MECHANICAL_PUMP_ARROW = get("mechanical_pump/arrow"), MECHANICAL_PUMP_COG = get("mechanical_pump/cog"),
|
||||
FLUID_PIPE_CASING = get("fluid_pipe/casing"),
|
||||
|
||||
|
||||
COUPLING_ATTACHMENT = getEntity("minecart_coupling/attachment"),
|
||||
COUPLING_RING = getEntity("minecart_coupling/ring"),
|
||||
COUPLING_CONNECTOR = getEntity("minecart_coupling/connector")
|
||||
|
||||
;
|
||||
|
||||
public static final Map<Direction, AllBlockPartials> PIPE_RIMS = map();
|
||||
;
|
||||
|
||||
public static final Map<AttachmentTypes, Map<Direction, AllBlockPartials>> PIPE_ATTACHMENTS = map();
|
||||
public static final Map<HeatLevel, AllBlockPartials> BLAZES = map();
|
||||
|
||||
static {
|
||||
|
@ -117,8 +101,16 @@ public class AllBlockPartials {
|
|||
private AllBlockPartials() {}
|
||||
|
||||
private static void populateMaps() {
|
||||
for (Direction d : Iterate.directions)
|
||||
PIPE_RIMS.put(d, get("fluid_pipe/rim/" + d.getName()));
|
||||
for (AttachmentTypes type : AttachmentTypes.values()) {
|
||||
if (!type.hasModel())
|
||||
continue;
|
||||
Map<Direction, AllBlockPartials> map = map();
|
||||
for (Direction d : Iterate.directions) {
|
||||
String asId = Lang.asId(type.name());
|
||||
map.put(d, get("fluid_pipe/" + asId + "/" + Lang.asId(d.getName())));
|
||||
}
|
||||
PIPE_ATTACHMENTS.put(type, map);
|
||||
}
|
||||
for (HeatLevel heat : HeatLevel.values()) {
|
||||
if (heat == HeatLevel.NONE)
|
||||
continue;
|
||||
|
@ -136,7 +128,7 @@ public class AllBlockPartials {
|
|||
all.add(partials);
|
||||
return partials;
|
||||
}
|
||||
|
||||
|
||||
private static AllBlockPartials get(String path) {
|
||||
AllBlockPartials partials = new AllBlockPartials();
|
||||
partials.modelLocation = new ResourceLocation(Create.ID, "block/" + path);
|
||||
|
|
|
@ -59,13 +59,15 @@ import com.simibubi.create.content.contraptions.components.structureMovement.pul
|
|||
import com.simibubi.create.content.contraptions.components.tracks.ReinforcedRailBlock;
|
||||
import com.simibubi.create.content.contraptions.components.turntable.TurntableBlock;
|
||||
import com.simibubi.create.content.contraptions.components.waterwheel.WaterWheelBlock;
|
||||
import com.simibubi.create.content.contraptions.fluids.FluidPipeBlock;
|
||||
import com.simibubi.create.content.contraptions.fluids.FluidPipeModel;
|
||||
import com.simibubi.create.content.contraptions.fluids.FluidTankBlock;
|
||||
import com.simibubi.create.content.contraptions.fluids.FluidTankGenerator;
|
||||
import com.simibubi.create.content.contraptions.fluids.FluidTankItem;
|
||||
import com.simibubi.create.content.contraptions.fluids.FluidTankModel;
|
||||
import com.simibubi.create.content.contraptions.fluids.PipeAttachmentModel;
|
||||
import com.simibubi.create.content.contraptions.fluids.PumpBlock;
|
||||
import com.simibubi.create.content.contraptions.fluids.pipes.EncasedPipeBlock;
|
||||
import com.simibubi.create.content.contraptions.fluids.pipes.FluidPipeBlock;
|
||||
import com.simibubi.create.content.contraptions.fluids.pipes.GlassFluidPipeBlock;
|
||||
import com.simibubi.create.content.contraptions.fluids.tank.FluidTankBlock;
|
||||
import com.simibubi.create.content.contraptions.fluids.tank.FluidTankGenerator;
|
||||
import com.simibubi.create.content.contraptions.fluids.tank.FluidTankItem;
|
||||
import com.simibubi.create.content.contraptions.fluids.tank.FluidTankModel;
|
||||
import com.simibubi.create.content.contraptions.processing.BasinBlock;
|
||||
import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock;
|
||||
import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlockItem;
|
||||
|
@ -219,12 +221,14 @@ public class AllBlocks {
|
|||
.build()
|
||||
.register();
|
||||
|
||||
public static final BlockEntry<EncasedShaftBlock> ENCASED_SHAFT = REGISTRATE.block("encased_shaft", EncasedShaftBlock::new)
|
||||
public static final BlockEntry<EncasedShaftBlock> ENCASED_SHAFT =
|
||||
REGISTRATE.block("encased_shaft", EncasedShaftBlock::new)
|
||||
.initialProperties(SharedProperties::stone)
|
||||
.properties(Block.Properties::nonOpaque)
|
||||
.transform(StressConfigDefaults.setNoImpact())
|
||||
//.blockstate(BlockStateGen.axisBlockProvider(true))
|
||||
.blockstate((c, p) -> axisBlock(c, p, blockState -> p.models().getExistingFile(p.modLoc("block/encased_shaft/" + blockState.get(EncasedShaftBlock.CASING).getName()))))
|
||||
.blockstate((c, p) -> axisBlock(c, p, blockState -> p.models()
|
||||
.getExistingFile(p.modLoc("block/encased_shaft/" + blockState.get(EncasedShaftBlock.CASING)
|
||||
.getName()))))
|
||||
.loot((p, b) -> p.registerDropping(b, SHAFT.get()))
|
||||
.register();
|
||||
|
||||
|
@ -461,14 +465,34 @@ public class AllBlocks {
|
|||
public static final BlockEntry<FluidPipeBlock> FLUID_PIPE = REGISTRATE.block("fluid_pipe", FluidPipeBlock::new)
|
||||
.initialProperties(SharedProperties::softMetal)
|
||||
.blockstate(BlockStateGen.pipe())
|
||||
.onRegister(CreateRegistrate.blockModel(() -> FluidPipeModel::new))
|
||||
.onRegister(CreateRegistrate.blockModel(() -> PipeAttachmentModel::new))
|
||||
.item()
|
||||
.transform(customItemModel())
|
||||
.register();
|
||||
|
||||
public static final BlockEntry<EncasedPipeBlock> ENCASED_FLUID_PIPE =
|
||||
REGISTRATE.block("encased_fluid_pipe", EncasedPipeBlock::new)
|
||||
.initialProperties(SharedProperties::softMetal)
|
||||
.blockstate((c, p) -> BlockStateGen.axisBlock(c, p, state -> p.models()
|
||||
.cubeColumn(c.getName(), p.modLoc("block/copper_casing"), p.modLoc("block/encased_pipe"))))
|
||||
.onRegister(CreateRegistrate.blockModel(() -> PipeAttachmentModel::new))
|
||||
.loot((p, b) -> p.registerDropping(b, FLUID_PIPE.get()))
|
||||
.register();
|
||||
|
||||
public static final BlockEntry<GlassFluidPipeBlock> GLASS_FLUID_PIPE =
|
||||
REGISTRATE.block("glass_fluid_pipe", GlassFluidPipeBlock::new)
|
||||
.initialProperties(SharedProperties::softMetal)
|
||||
.addLayer(() -> RenderType::getCutoutMipped)
|
||||
.blockstate((c, p) -> BlockStateGen.axisBlock(c, p, s -> p.models()
|
||||
.getExistingFile(p.modLoc("block/fluid_pipe/window" + (s.get(GlassFluidPipeBlock.ALT) ? "_alt" : "")))))
|
||||
.onRegister(CreateRegistrate.blockModel(() -> PipeAttachmentModel::new))
|
||||
.loot((p, b) -> p.registerDropping(b, FLUID_PIPE.get()))
|
||||
.register();
|
||||
|
||||
public static final BlockEntry<PumpBlock> MECHANICAL_PUMP = REGISTRATE.block("mechanical_pump", PumpBlock::new)
|
||||
.initialProperties(SharedProperties::softMetal)
|
||||
.blockstate(BlockStateGen.directionalBlockProviderIgnoresWaterlogged(true))
|
||||
.onRegister(CreateRegistrate.blockModel(() -> PipeAttachmentModel::new))
|
||||
.transform(StressConfigDefaults.setImpact(4.0))
|
||||
.item()
|
||||
.transform(customItemModel())
|
||||
|
|
|
@ -6,6 +6,7 @@ import static net.minecraft.util.Direction.UP;
|
|||
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import com.simibubi.create.content.logistics.block.chute.ChuteShapes;
|
||||
import com.simibubi.create.foundation.utility.VoxelShaper;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
|
@ -28,6 +29,7 @@ public class AllShapes {
|
|||
CASING_11PX = shape(0, 0, 0, 16, 11, 16).forDirectional(),
|
||||
MOTOR_BLOCK = shape(3, 0, 3, 13, 14, 13).forDirectional(),
|
||||
FOUR_VOXEL_POLE = shape(6, 0, 6, 10, 16, 10).forAxis(), SIX_VOXEL_POLE = shape(5, 0, 5, 11, 16, 11).forAxis(),
|
||||
EIGHT_VOXEL_POLE = shape(4, 0, 4, 12, 16, 12).forAxis(),
|
||||
EXTRACTOR = shape(4, 2, 11, 12, 10, 17).forDirectional(SOUTH)
|
||||
.withVerticalShapes(cuboid(4, 11, 4, 12, 17, 12)),
|
||||
TRANSPOSER = shape(4, 4, -1, 12, 12, 1).add(5, 5, 0, 11, 11, 16)
|
||||
|
@ -111,14 +113,16 @@ public class AllShapes {
|
|||
// Static Block Shapes
|
||||
public static final VoxelShape
|
||||
|
||||
BASIN_BLOCK_SHAPE = shape(0, 2, 0, 16, 13, 16).erase(2, 5, 2, 14, 14, 14)
|
||||
BASIN_BLOCK_SHAPE = shape(0, 2, 0, 16, 16, 16).erase(2, 2, 2, 14, 16, 14)
|
||||
.add(2, 0, 2, 14, 2, 14)
|
||||
.build(), HEATER_BLOCK_SHAPE =
|
||||
shape(2, 0, 2, 14, 14, 14).add(0, 0, 0, 16, 4, 16)
|
||||
.build(), BASIN_COLLISION_SHAPE =
|
||||
shape(0, 2, 0, 16, 16, 16).erase(2, 5, 2, 14, 16, 14)
|
||||
.add(2, 0, 2, 14, 2, 14)
|
||||
.build(),
|
||||
HEATER_BLOCK_SHAPE = shape(2, 0, 2, 14, 14, 14).add(0, 0, 0, 16, 4, 16)
|
||||
.build(),
|
||||
HEATER_BLOCK_SPECIAL_COLLISION_SHAPE = shape(0, 0, 0, 16, 4, 16).build(),
|
||||
CRUSHING_WHEEL_COLLISION_SHAPE = cuboid(0, 0, 0, 16, 22, 16),
|
||||
SEAT = cuboid(0, 0, 0, 16, 8, 16),
|
||||
CRUSHING_WHEEL_COLLISION_SHAPE = cuboid(0, 0, 0, 16, 22, 16), SEAT = cuboid(0, 0, 0, 16, 8, 16),
|
||||
SEAT_COLLISION = cuboid(0, 0, 0, 16, 6, 16),
|
||||
MECHANICAL_PROCESSOR_SHAPE = shape(VoxelShapes.fullCube()).erase(4, 0, 4, 12, 16, 12)
|
||||
.build(),
|
||||
|
@ -171,7 +175,8 @@ public class AllShapes {
|
|||
LOGISTICS_TABLE = shape(TABLE_POLE_SHAPE).add(LOGISTICS_TABLE_SLOPE)
|
||||
.forHorizontal(SOUTH),
|
||||
SCHEMATICS_TABLE = shape(TABLE_POLE_SHAPE).add(SCHEMATICS_TABLE_SLOPE)
|
||||
.forDirectional(SOUTH)
|
||||
.forDirectional(SOUTH),
|
||||
CHUTE_SLOPE = shape(ChuteShapes.createSlope()).forHorizontal(SOUTH)
|
||||
|
||||
;
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ public enum AllSoundEvents implements IDataProvider {
|
|||
AllSoundEvents() {
|
||||
id = Lang.asId(name());
|
||||
}
|
||||
|
||||
|
||||
AllSoundEvents(String name) {
|
||||
id = name;
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ public enum AllSoundEvents implements IDataProvider {
|
|||
return id;
|
||||
}
|
||||
|
||||
public AllSoundEvents generator(DataGenerator generator){
|
||||
public AllSoundEvents generator(DataGenerator generator) {
|
||||
this.generator = generator;
|
||||
return this;
|
||||
}
|
||||
|
@ -83,7 +83,9 @@ public enum AllSoundEvents implements IDataProvider {
|
|||
}
|
||||
|
||||
public void generate(Path path, DirectoryCache cache) {
|
||||
Gson GSON = (new GsonBuilder()).setPrettyPrinting().disableHtmlEscaping().create();
|
||||
Gson GSON = (new GsonBuilder()).setPrettyPrinting()
|
||||
.disableHtmlEscaping()
|
||||
.create();
|
||||
path = path.resolve("assets/create");
|
||||
|
||||
try {
|
||||
|
@ -94,7 +96,8 @@ public enum AllSoundEvents implements IDataProvider {
|
|||
if (soundEvent.child != null) {
|
||||
// wrapper
|
||||
JsonObject s = new JsonObject();
|
||||
s.addProperty("name", soundEvent.child.getName().toString());
|
||||
s.addProperty("name", soundEvent.child.getName()
|
||||
.toString());
|
||||
s.addProperty("type", "event");
|
||||
arr.add(s);
|
||||
} else {
|
||||
|
@ -120,6 +123,6 @@ public enum AllSoundEvents implements IDataProvider {
|
|||
|
||||
@Override
|
||||
public String getName() {
|
||||
return null;
|
||||
return "Create's Custom Sound: " + name();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ public enum AllSpecialTextures {
|
|||
BLANK("blank.png"),
|
||||
CHECKERED("checkerboard.png"),
|
||||
THIN_CHECKERED("thin_checkerboard.png"),
|
||||
CUTOUT_CHECKERED("cutout_checkerboard.png"),
|
||||
HIGHLIGHT_CHECKERED("highlighted_checkerboard.png"),
|
||||
SELECTION("selection.png"),
|
||||
|
||||
|
|
|
@ -43,10 +43,13 @@ import com.simibubi.create.content.contraptions.components.structureMovement.pul
|
|||
import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyTileEntity;
|
||||
import com.simibubi.create.content.contraptions.components.turntable.TurntableTileEntity;
|
||||
import com.simibubi.create.content.contraptions.components.waterwheel.WaterWheelTileEntity;
|
||||
import com.simibubi.create.content.contraptions.fluids.FluidTankRenderer;
|
||||
import com.simibubi.create.content.contraptions.fluids.FluidTankTileEntity;
|
||||
import com.simibubi.create.content.contraptions.fluids.PumpRenderer;
|
||||
import com.simibubi.create.content.contraptions.fluids.PumpTileEntity;
|
||||
import com.simibubi.create.content.contraptions.fluids.pipes.FluidPipeTileEntity;
|
||||
import com.simibubi.create.content.contraptions.fluids.pipes.StraightPipeTileEntity;
|
||||
import com.simibubi.create.content.contraptions.fluids.pipes.TransparentStraightPipeRenderer;
|
||||
import com.simibubi.create.content.contraptions.fluids.tank.FluidTankRenderer;
|
||||
import com.simibubi.create.content.contraptions.fluids.tank.FluidTankTileEntity;
|
||||
import com.simibubi.create.content.contraptions.processing.BasinRenderer;
|
||||
import com.simibubi.create.content.contraptions.processing.BasinTileEntity;
|
||||
import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerRenderer;
|
||||
|
@ -57,7 +60,11 @@ import com.simibubi.create.content.contraptions.relays.advanced.sequencer.Sequen
|
|||
import com.simibubi.create.content.contraptions.relays.belt.BeltRenderer;
|
||||
import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity;
|
||||
import com.simibubi.create.content.contraptions.relays.elementary.SimpleKineticTileEntity;
|
||||
import com.simibubi.create.content.contraptions.relays.encased.*;
|
||||
import com.simibubi.create.content.contraptions.relays.encased.AdjustablePulleyTileEntity;
|
||||
import com.simibubi.create.content.contraptions.relays.encased.ClutchTileEntity;
|
||||
import com.simibubi.create.content.contraptions.relays.encased.EncasedShaftRenderer;
|
||||
import com.simibubi.create.content.contraptions.relays.encased.EncasedShaftTileEntity;
|
||||
import com.simibubi.create.content.contraptions.relays.encased.SplitShaftRenderer;
|
||||
import com.simibubi.create.content.contraptions.relays.gauge.GaugeRenderer;
|
||||
import com.simibubi.create.content.contraptions.relays.gauge.SpeedGaugeTileEntity;
|
||||
import com.simibubi.create.content.contraptions.relays.gauge.StressGaugeTileEntity;
|
||||
|
@ -86,7 +93,12 @@ import com.simibubi.create.content.logistics.block.mechanicalArm.ArmRenderer;
|
|||
import com.simibubi.create.content.logistics.block.mechanicalArm.ArmTileEntity;
|
||||
import com.simibubi.create.content.logistics.block.packager.PackagerRenderer;
|
||||
import com.simibubi.create.content.logistics.block.packager.PackagerTileEntity;
|
||||
import com.simibubi.create.content.logistics.block.redstone.*;
|
||||
import com.simibubi.create.content.logistics.block.redstone.AnalogLeverRenderer;
|
||||
import com.simibubi.create.content.logistics.block.redstone.AnalogLeverTileEntity;
|
||||
import com.simibubi.create.content.logistics.block.redstone.NixieTubeRenderer;
|
||||
import com.simibubi.create.content.logistics.block.redstone.NixieTubeTileEntity;
|
||||
import com.simibubi.create.content.logistics.block.redstone.RedstoneLinkTileEntity;
|
||||
import com.simibubi.create.content.logistics.block.redstone.StockpileSwitchTileEntity;
|
||||
import com.simibubi.create.content.logistics.block.transposer.LinkedTransposerTileEntity;
|
||||
import com.simibubi.create.content.logistics.block.transposer.TransposerTileEntity;
|
||||
import com.simibubi.create.content.schematics.block.SchematicTableTileEntity;
|
||||
|
@ -95,6 +107,7 @@ import com.simibubi.create.content.schematics.block.SchematicannonTileEntity;
|
|||
import com.simibubi.create.foundation.tileEntity.renderer.SmartTileEntityRenderer;
|
||||
import com.tterrag.registrate.util.entry.TileEntityEntry;
|
||||
import com.tterrag.registrate.util.nullness.NonNullFunction;
|
||||
|
||||
import net.minecraft.tileentity.TileEntityType;
|
||||
|
||||
public class AllTileEntities {
|
||||
|
@ -191,6 +204,22 @@ public class AllTileEntities {
|
|||
.renderer(() -> PumpRenderer::new)
|
||||
.register();
|
||||
|
||||
public static final TileEntityEntry<FluidPipeTileEntity> FLUID_PIPE = Create.registrate()
|
||||
.tileEntity("fluid_pipe", FluidPipeTileEntity::new)
|
||||
.validBlocks(AllBlocks.FLUID_PIPE)
|
||||
.register();
|
||||
|
||||
public static final TileEntityEntry<StraightPipeTileEntity> ENCASED_FLUID_PIPE = Create.registrate()
|
||||
.tileEntity("encased_fluid_pipe", StraightPipeTileEntity::new)
|
||||
.validBlocks(AllBlocks.ENCASED_FLUID_PIPE)
|
||||
.register();
|
||||
|
||||
public static final TileEntityEntry<StraightPipeTileEntity> GLASS_FLUID_PIPE = Create.registrate()
|
||||
.tileEntity("glass_fluid_pipe", StraightPipeTileEntity::new)
|
||||
.validBlocks(AllBlocks.GLASS_FLUID_PIPE)
|
||||
.renderer(() -> TransparentStraightPipeRenderer::new)
|
||||
.register();
|
||||
|
||||
public static final TileEntityEntry<FluidTankTileEntity> FLUID_TANK = Create.registrate()
|
||||
.tileEntity("fluid_tank", (NonNullFunction<TileEntityType<FluidTankTileEntity>, ? extends FluidTankTileEntity>) FluidTankTileEntity::new)
|
||||
.validBlocks(AllBlocks.FLUID_TANK)
|
||||
|
|
|
@ -15,6 +15,7 @@ import com.simibubi.create.foundation.command.ServerLagger;
|
|||
import com.simibubi.create.foundation.config.AllConfigs;
|
||||
import com.simibubi.create.foundation.data.CreateRegistrate;
|
||||
import com.simibubi.create.foundation.data.LangMerger;
|
||||
import com.simibubi.create.foundation.data.StandardRecipes;
|
||||
import com.simibubi.create.foundation.networking.AllPackets;
|
||||
import com.simibubi.create.foundation.worldgen.AllWorldFeatures;
|
||||
import com.tterrag.registrate.util.NonNullLazyValue;
|
||||
|
@ -102,6 +103,7 @@ public class Create {
|
|||
DataGenerator gen = event.getGenerator();
|
||||
gen.addProvider(new AllAdvancements(gen));
|
||||
gen.addProvider(new LangMerger(gen));
|
||||
gen.addProvider(new StandardRecipes(gen));
|
||||
gen.addProvider(AllSoundEvents.BLAZE_MUNCH.generator(gen));
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ public class KineticDebugger {
|
|||
VoxelShape shape = world.getBlockState(toOutline)
|
||||
.getRenderShape(world, toOutline);
|
||||
|
||||
if (te.getTheoreticalSpeed() != 0)
|
||||
if (te.getTheoreticalSpeed() != 0 && !shape.isEmpty())
|
||||
CreateClient.outliner.chaseAABB("kineticSource", shape.getBoundingBox()
|
||||
.offset(toOutline))
|
||||
.lineWidth(1 / 16f)
|
||||
|
|
|
@ -178,7 +178,7 @@ public abstract class KineticTileEntity extends SmartTileEntity
|
|||
}
|
||||
|
||||
@Override
|
||||
public CompoundNBT write(CompoundNBT compound) {
|
||||
protected void write(CompoundNBT compound, boolean clientPacket) {
|
||||
compound.putFloat("Speed", speed);
|
||||
|
||||
if (needsSpeedUpdate())
|
||||
|
@ -202,7 +202,7 @@ public abstract class KineticTileEntity extends SmartTileEntity
|
|||
compound.put("Network", networkTag);
|
||||
}
|
||||
|
||||
return super.write(compound);
|
||||
super.write(compound, clientPacket);
|
||||
}
|
||||
|
||||
public boolean needsSpeedUpdate() {
|
||||
|
@ -210,12 +210,13 @@ public abstract class KineticTileEntity extends SmartTileEntity
|
|||
}
|
||||
|
||||
@Override
|
||||
public void read(CompoundNBT compound) {
|
||||
protected void read(CompoundNBT compound, boolean clientPacket) {
|
||||
boolean overStressedBefore = overStressed;
|
||||
clearKineticInformation();
|
||||
|
||||
// DO NOT READ kinetic information when placed after movement
|
||||
if (wasMoved) {
|
||||
super.read(compound);
|
||||
super.read(compound, clientPacket);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -235,14 +236,9 @@ public abstract class KineticTileEntity extends SmartTileEntity
|
|||
overStressed = capacity < stress && StressImpact.isEnabled();
|
||||
}
|
||||
|
||||
super.read(compound);
|
||||
}
|
||||
super.read(compound, clientPacket);
|
||||
|
||||
@Override
|
||||
public void readClientUpdate(CompoundNBT tag) {
|
||||
boolean overStressedBefore = overStressed;
|
||||
super.readClientUpdate(tag);
|
||||
if (overStressedBefore != overStressed && speed != 0)
|
||||
if (clientPacket && overStressedBefore != overStressed && speed != 0)
|
||||
effects.triggerOverStressedEffect();
|
||||
}
|
||||
|
||||
|
@ -450,7 +446,7 @@ public abstract class KineticTileEntity extends SmartTileEntity
|
|||
public int getFlickerScore() {
|
||||
return flickerTally;
|
||||
}
|
||||
|
||||
|
||||
public static float convertToDirection(float axisSpeed, Direction d) {
|
||||
return d.getAxisDirection() == AxisDirection.POSITIVE ? axisSpeed : -axisSpeed;
|
||||
}
|
||||
|
|
|
@ -58,21 +58,21 @@ public abstract class BlockBreakingKineticTileEntity extends KineticTileEntity {
|
|||
}
|
||||
|
||||
@Override
|
||||
public CompoundNBT write(CompoundNBT compound) {
|
||||
public void write(CompoundNBT compound, boolean clientPacket) {
|
||||
compound.putInt("Progress", destroyProgress);
|
||||
compound.putInt("NextTick", ticksUntilNextProgress);
|
||||
if (breakingPos != null)
|
||||
compound.put("Breaking", NBTUtil.writeBlockPos(breakingPos));
|
||||
return super.write(compound);
|
||||
super.write(compound, clientPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(CompoundNBT compound) {
|
||||
protected void read(CompoundNBT compound, boolean clientPacket) {
|
||||
destroyProgress = compound.getInt("Progress");
|
||||
ticksUntilNextProgress = compound.getInt("NextTick");
|
||||
if (compound.contains("Breaking"))
|
||||
breakingPos = NBTUtil.readBlockPos(compound.getCompound("Breaking"));
|
||||
super.read(compound);
|
||||
super.read(compound, clientPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -3,7 +3,6 @@ package com.simibubi.create.content.contraptions.components.actors;
|
|||
import java.util.UUID;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour;
|
||||
|
||||
import net.minecraft.world.server.ServerWorld;
|
||||
import net.minecraftforge.common.util.FakePlayer;
|
||||
|
|
|
@ -39,23 +39,23 @@ public class CuckooClockTileEntity extends KineticTileEntity {
|
|||
super(type);
|
||||
animationType = Animation.NONE;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public CompoundNBT writeToClient(CompoundNBT compound) {
|
||||
if (sendAnimationUpdate)
|
||||
NBTHelper.writeEnum(compound, "Animation", animationType);
|
||||
sendAnimationUpdate = false;
|
||||
return super.writeToClient(compound);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readClientUpdate(CompoundNBT tag) {
|
||||
if (tag.contains("Animation")) {
|
||||
animationType = NBTHelper.readEnum(tag, "Animation", Animation.class);
|
||||
protected void read(CompoundNBT compound, boolean clientPacket) {
|
||||
super.read(compound, clientPacket);
|
||||
if (clientPacket && compound.contains("Animation")) {
|
||||
animationType = NBTHelper.readEnum(compound, "Animation", Animation.class);
|
||||
animationProgress.lastValue = 0;
|
||||
animationProgress.value = 0;
|
||||
}
|
||||
super.readClientUpdate(tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(CompoundNBT compound, boolean clientPacket) {
|
||||
if (clientPacket && sendAnimationUpdate)
|
||||
NBTHelper.writeEnum(compound, "Animation", animationType);
|
||||
sendAnimationUpdate = false;
|
||||
super.write(compound, clientPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -123,7 +123,7 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity {
|
|||
}
|
||||
|
||||
@Override
|
||||
public CompoundNBT write(CompoundNBT compound) {
|
||||
public void write(CompoundNBT compound, boolean clientPacket) {
|
||||
compound.put("Inventory", inventory.serializeNBT());
|
||||
|
||||
CompoundNBT inputNBT = new CompoundNBT();
|
||||
|
@ -138,43 +138,19 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity {
|
|||
compound.putInt("CountDown", countDown);
|
||||
compound.putBoolean("Cover", covered);
|
||||
|
||||
return super.write(compound);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundNBT writeToClient(CompoundNBT tag) {
|
||||
if (reRender) {
|
||||
tag.putBoolean("Redraw", true);
|
||||
super.write(compound, clientPacket);
|
||||
|
||||
if (clientPacket && reRender) {
|
||||
compound.putBoolean("Redraw", true);
|
||||
reRender = false;
|
||||
}
|
||||
return super.writeToClient(tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readClientUpdate(CompoundNBT tag) {
|
||||
if (tag.contains("Redraw"))
|
||||
world.notifyBlockUpdate(getPos(), getBlockState(), getBlockState(), 16);
|
||||
|
||||
protected void read(CompoundNBT compound, boolean clientPacket) {
|
||||
Phase phaseBefore = phase;
|
||||
GroupedItems before = this.groupedItems;
|
||||
|
||||
super.readClientUpdate(tag);
|
||||
|
||||
if (phaseBefore != phase && phase == Phase.CRAFTING)
|
||||
groupedItemsBeforeCraft = before;
|
||||
if (phaseBefore == Phase.EXPORTING && phase == Phase.WAITING) {
|
||||
Direction facing = getBlockState().get(MechanicalCrafterBlock.HORIZONTAL_FACING);
|
||||
Vec3d vec = new Vec3d(facing.getDirectionVec()).scale(.75)
|
||||
.add(VecHelper.getCenterOf(pos));
|
||||
Direction targetDirection = MechanicalCrafterBlock.getTargetDirection(getBlockState());
|
||||
vec = vec.add(new Vec3d(targetDirection.getDirectionVec()).scale(1));
|
||||
world.addParticle(ParticleTypes.CRIT, vec.x, vec.y, vec.z, 0, 0, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(CompoundNBT compound) {
|
||||
|
||||
inventory.deserializeNBT(compound.getCompound("Inventory"));
|
||||
input.read(compound.getCompound("ConnectedInput"));
|
||||
groupedItems = GroupedItems.read(compound.getCompound("GroupedItems"));
|
||||
|
@ -186,7 +162,22 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity {
|
|||
this.phase = phase;
|
||||
countDown = compound.getInt("CountDown");
|
||||
covered = compound.getBoolean("Cover");
|
||||
super.read(compound);
|
||||
super.read(compound, clientPacket);
|
||||
|
||||
if (!clientPacket)
|
||||
return;
|
||||
if (compound.contains("Redraw"))
|
||||
world.notifyBlockUpdate(getPos(), getBlockState(), getBlockState(), 16);
|
||||
if (phaseBefore != phase && phase == Phase.CRAFTING)
|
||||
groupedItemsBeforeCraft = before;
|
||||
if (phaseBefore == Phase.EXPORTING && phase == Phase.WAITING) {
|
||||
Direction facing = getBlockState().get(MechanicalCrafterBlock.HORIZONTAL_FACING);
|
||||
Vec3d vec = new Vec3d(facing.getDirectionVec()).scale(.75)
|
||||
.add(VecHelper.getCenterOf(pos));
|
||||
Direction targetDirection = MechanicalCrafterBlock.getTargetDirection(getBlockState());
|
||||
vec = vec.add(new Vec3d(targetDirection.getDirectionVec()).scale(1));
|
||||
world.addParticle(ParticleTypes.CRIT, vec.x, vec.y, vec.z, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -293,7 +284,7 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity {
|
|||
Vec3d vec = facingVec.scale(.65)
|
||||
.add(VecHelper.getCenterOf(pos));
|
||||
Vec3d offset = VecHelper.offsetRandomly(Vec3d.ZERO, world.rand, .125f)
|
||||
.mul(VecHelper.planeByNormal(facingVec))
|
||||
.mul(VecHelper.axisAlingedPlaneOf(facingVec))
|
||||
.normalize()
|
||||
.scale(progress * .5f)
|
||||
.add(vec);
|
||||
|
@ -307,7 +298,7 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity {
|
|||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
Vec3d randVec = VecHelper.offsetRandomly(Vec3d.ZERO, world.rand, .125f)
|
||||
.mul(VecHelper.planeByNormal(facingVec))
|
||||
.mul(VecHelper.axisAlingedPlaneOf(facingVec))
|
||||
.normalize()
|
||||
.scale(.25f);
|
||||
Vec3d offset2 = randVec.add(vec);
|
||||
|
|
|
@ -38,15 +38,15 @@ public class HandCrankTileEntity extends GeneratingKineticTileEntity {
|
|||
}
|
||||
|
||||
@Override
|
||||
public CompoundNBT write(CompoundNBT compound) {
|
||||
public void write(CompoundNBT compound, boolean clientPacket) {
|
||||
compound.putInt("InUse", inUse);
|
||||
return super.write(compound);
|
||||
super.write(compound, clientPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(CompoundNBT compound) {
|
||||
protected void read(CompoundNBT compound, boolean clientPacket) {
|
||||
inUse = compound.getInt("InUse");
|
||||
super.read(compound);
|
||||
super.read(compound, clientPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -215,19 +215,17 @@ public class CrushingWheelControllerTileEntity extends SmartTileEntity {
|
|||
}
|
||||
|
||||
@Override
|
||||
public CompoundNBT write(CompoundNBT compound) {
|
||||
public void write(CompoundNBT compound, boolean clientPacket) {
|
||||
if (hasEntity())
|
||||
compound.put("Entity", NBTUtil.writeUniqueId(entityUUID));
|
||||
compound.put("Inventory", inventory.serializeNBT());
|
||||
compound.putFloat("Speed", crushingspeed);
|
||||
|
||||
return super.write(compound);
|
||||
super.write(compound, clientPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(CompoundNBT compound) {
|
||||
super.read(compound);
|
||||
|
||||
protected void read(CompoundNBT compound, boolean clientPacket) {
|
||||
super.read(compound, clientPacket);
|
||||
if (compound.contains("Entity") && !isFrozen() && !isOccupied()) {
|
||||
entityUUID = NBTUtil.readUniqueId(compound.getCompound("Entity"));
|
||||
this.searchForEntity = true;
|
||||
|
|
|
@ -51,11 +51,10 @@ import net.minecraftforge.items.ItemHandlerHelper;
|
|||
|
||||
public class DeployerTileEntity extends KineticTileEntity {
|
||||
|
||||
private static final List<Pair<BlockPos, Direction>> EXTRACTING_LOCATIONS = Arrays
|
||||
.asList(Direction.values())
|
||||
.stream()
|
||||
.map(d -> Pair.of(BlockPos.ZERO.offset(d), d.getOpposite()))
|
||||
.collect(Collectors.toList());
|
||||
private static final List<Pair<BlockPos, Direction>> EXTRACTING_LOCATIONS = Arrays.asList(Direction.values())
|
||||
.stream()
|
||||
.map(d -> Pair.of(BlockPos.ZERO.offset(d), d.getOpposite()))
|
||||
.collect(Collectors.toList());
|
||||
private FilteringBehaviour filtering;
|
||||
private ExtractingBehaviour extracting;
|
||||
|
||||
|
@ -167,7 +166,8 @@ public class DeployerTileEntity extends KineticTileEntity {
|
|||
return;
|
||||
}
|
||||
|
||||
if (filtering.getFilter().isEmpty() && stack.isEmpty())
|
||||
if (filtering.getFilter()
|
||||
.isEmpty() && stack.isEmpty())
|
||||
extracting.extract(1);
|
||||
|
||||
Direction facing = getBlockState().get(FACING);
|
||||
|
@ -182,12 +182,16 @@ public class DeployerTileEntity extends KineticTileEntity {
|
|||
|
||||
state = State.EXPANDING;
|
||||
Vec3d movementVector = getMovementVector();
|
||||
Vec3d rayOrigin = VecHelper.getCenterOf(pos).add(movementVector.scale(3 / 2f));
|
||||
Vec3d rayTarget = VecHelper.getCenterOf(pos).add(movementVector.scale(5 / 2f));
|
||||
Vec3d rayOrigin = VecHelper.getCenterOf(pos)
|
||||
.add(movementVector.scale(3 / 2f));
|
||||
Vec3d rayTarget = VecHelper.getCenterOf(pos)
|
||||
.add(movementVector.scale(5 / 2f));
|
||||
RayTraceContext rayTraceContext =
|
||||
new RayTraceContext(rayOrigin, rayTarget, BlockMode.OUTLINE, FluidMode.NONE, player);
|
||||
BlockRayTraceResult result = world.rayTraceBlocks(rayTraceContext);
|
||||
reach = (float) (.5f + Math.min(result.getHitVec().subtract(rayOrigin).length(), .75f));
|
||||
reach = (float) (.5f + Math.min(result.getHitVec()
|
||||
.subtract(rayOrigin)
|
||||
.length(), .75f));
|
||||
|
||||
timer = 1000;
|
||||
sendData();
|
||||
|
@ -226,7 +230,9 @@ public class DeployerTileEntity extends KineticTileEntity {
|
|||
if (!(otherTile instanceof DeployerTileEntity))
|
||||
return false;
|
||||
DeployerTileEntity deployerTile = (DeployerTileEntity) otherTile;
|
||||
if (world.getBlockState(otherDeployer).get(FACING).getOpposite() != facing || deployerTile.mode != Mode.PUNCH)
|
||||
if (world.getBlockState(otherDeployer)
|
||||
.get(FACING)
|
||||
.getOpposite() != facing || deployerTile.mode != Mode.PUNCH)
|
||||
return false;
|
||||
|
||||
boop = true;
|
||||
|
@ -295,13 +301,15 @@ public class DeployerTileEntity extends KineticTileEntity {
|
|||
}
|
||||
|
||||
protected void tryDisposeOfItems() {
|
||||
boolean noInv = extracting.getInventories().isEmpty();
|
||||
boolean noInv = extracting.getInventories()
|
||||
.isEmpty();
|
||||
for (Iterator<ItemStack> iterator = overflowItems.iterator(); iterator.hasNext();) {
|
||||
ItemStack itemStack = iterator.next();
|
||||
|
||||
if (noInv) {
|
||||
Vec3d offset = getMovementVector();
|
||||
Vec3d outPos = VecHelper.getCenterOf(pos).add(offset.scale(-.65f));
|
||||
Vec3d outPos = VecHelper.getCenterOf(pos)
|
||||
.add(offset.scale(-.65f));
|
||||
Vec3d motion = offset.scale(-.25f);
|
||||
ItemEntity e = new ItemEntity(world, outPos.x, outPos.y, outPos.z, itemStack.copy());
|
||||
e.setMotion(motion);
|
||||
|
@ -328,11 +336,12 @@ public class DeployerTileEntity extends KineticTileEntity {
|
|||
protected Vec3d getMovementVector() {
|
||||
if (!AllBlocks.DEPLOYER.has(getBlockState()))
|
||||
return Vec3d.ZERO;
|
||||
return new Vec3d(getBlockState().get(FACING).getDirectionVec());
|
||||
return new Vec3d(getBlockState().get(FACING)
|
||||
.getDirectionVec());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(CompoundNBT compound) {
|
||||
protected void read(CompoundNBT compound, boolean clientPacket) {
|
||||
state = NBTHelper.readEnum(compound, "State", State.class);
|
||||
mode = NBTHelper.readEnum(compound, "Mode", Mode.class);
|
||||
timer = compound.getInt("Timer");
|
||||
|
@ -340,48 +349,45 @@ public class DeployerTileEntity extends KineticTileEntity {
|
|||
overflowItems = NBTHelper.readItemList(compound.getList("Overflow", NBT.TAG_COMPOUND));
|
||||
if (compound.contains("HeldItem"))
|
||||
heldItem = ItemStack.read(compound.getCompound("HeldItem"));
|
||||
super.read(compound);
|
||||
super.read(compound, clientPacket);
|
||||
|
||||
if (!clientPacket)
|
||||
return;
|
||||
reach = compound.getFloat("Reach");
|
||||
if (compound.contains("Particle")) {
|
||||
ItemStack particleStack = ItemStack.read(compound.getCompound("Particle"));
|
||||
SandPaperItem.spawnParticles(VecHelper.getCenterOf(pos)
|
||||
.add(getMovementVector().scale(2f)), particleStack, this.world);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundNBT write(CompoundNBT compound) {
|
||||
public void write(CompoundNBT compound, boolean clientPacket) {
|
||||
NBTHelper.writeEnum(compound, "Mode", mode);
|
||||
NBTHelper.writeEnum(compound, "State", state);
|
||||
compound.putInt("Timer", timer);
|
||||
if (player != null) {
|
||||
compound.put("HeldItem", player.getHeldItemMainhand().serializeNBT());
|
||||
compound.put("HeldItem", player.getHeldItemMainhand()
|
||||
.serializeNBT());
|
||||
ListNBT invNBT = new ListNBT();
|
||||
player.inventory.write(invNBT);
|
||||
compound.put("Inventory", invNBT);
|
||||
compound.put("Overflow", NBTHelper.writeItemList(overflowItems));
|
||||
}
|
||||
return super.write(compound);
|
||||
}
|
||||
|
||||
super.write(compound, clientPacket);
|
||||
|
||||
@Override
|
||||
public CompoundNBT writeToClient(CompoundNBT compound) {
|
||||
if (!clientPacket)
|
||||
return;
|
||||
compound.putFloat("Reach", reach);
|
||||
if (player != null) {
|
||||
compound.put("HeldItem", player.getHeldItemMainhand().serializeNBT());
|
||||
if (player.spawnedItemEffects != null) {
|
||||
compound.put("Particle", player.spawnedItemEffects.serializeNBT());
|
||||
player.spawnedItemEffects = null;
|
||||
}
|
||||
if (player == null)
|
||||
return;
|
||||
compound.put("HeldItem", player.getHeldItemMainhand()
|
||||
.serializeNBT());
|
||||
if (player.spawnedItemEffects != null) {
|
||||
compound.put("Particle", player.spawnedItemEffects.serializeNBT());
|
||||
player.spawnedItemEffects = null;
|
||||
}
|
||||
return super.writeToClient(compound);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readClientUpdate(CompoundNBT tag) {
|
||||
reach = tag.getFloat("Reach");
|
||||
if (tag.contains("Particle")) {
|
||||
ItemStack particleStack = ItemStack.read(tag.getCompound("Particle"));
|
||||
SandPaperItem
|
||||
.spawnParticles(VecHelper.getCenterOf(pos).add(getMovementVector().scale(2f)), particleStack,
|
||||
this.world);
|
||||
}
|
||||
|
||||
super.readClientUpdate(tag);
|
||||
}
|
||||
|
||||
private IItemHandlerModifiable createHandler() {
|
||||
|
@ -395,7 +401,7 @@ public class DeployerTileEntity extends KineticTileEntity {
|
|||
|
||||
public AllBlockPartials getHandPose() {
|
||||
return mode == Mode.PUNCH ? AllBlockPartials.DEPLOYER_HAND_PUNCHING
|
||||
: heldItem.isEmpty() ? AllBlockPartials.DEPLOYER_HAND_POINTING : AllBlockPartials.DEPLOYER_HAND_HOLDING;
|
||||
: heldItem.isEmpty() ? AllBlockPartials.DEPLOYER_HAND_POINTING : AllBlockPartials.DEPLOYER_HAND_HOLDING;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -165,7 +165,7 @@ public class AirCurrent {
|
|||
.get(BlockStateProperties.FACING);
|
||||
pushing = source.getAirFlowDirection() == direction;
|
||||
Vec3d directionVec = new Vec3d(direction.getDirectionVec());
|
||||
Vec3d planeVec = VecHelper.planeByNormal(directionVec);
|
||||
Vec3d planeVec = VecHelper.axisAlingedPlaneOf(directionVec);
|
||||
|
||||
// 4 Rays test for holes in the shapes blocking the flow
|
||||
float offsetDistance = .25f;
|
||||
|
|
|
@ -6,6 +6,7 @@ import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlo
|
|||
import com.simibubi.create.content.logistics.block.chute.ChuteTileEntity;
|
||||
import com.simibubi.create.foundation.config.AllConfigs;
|
||||
import com.simibubi.create.foundation.config.CKinetics;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.state.properties.BlockStateProperties;
|
||||
|
@ -30,21 +31,17 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void readClientUpdate(CompoundNBT tag) {
|
||||
super.readClientUpdate(tag);
|
||||
airCurrent.rebuild();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(CompoundNBT compound) {
|
||||
super.read(compound);
|
||||
protected void read(CompoundNBT compound, boolean clientPacket) {
|
||||
super.read(compound, clientPacket);
|
||||
isGenerator = compound.getBoolean("Generating");
|
||||
if (clientPacket)
|
||||
airCurrent.rebuild();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundNBT write(CompoundNBT compound) {
|
||||
public void write(CompoundNBT compound, boolean clientPacket) {
|
||||
compound.putBoolean("Generating", isGenerator);
|
||||
return super.write(compound);
|
||||
super.write(compound, clientPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -77,10 +74,12 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity {
|
|||
return false;
|
||||
BlockState checkState = world.getBlockState(pos.down());
|
||||
|
||||
if (!checkState.getBlock().isIn(AllBlockTags.FAN_HEATERS.tag))
|
||||
if (!checkState.getBlock()
|
||||
.isIn(AllBlockTags.FAN_HEATERS.tag))
|
||||
return false;
|
||||
|
||||
if (checkState.has(BlazeBurnerBlock.HEAT_LEVEL) && !checkState.get(BlazeBurnerBlock.HEAT_LEVEL).isAtLeast(BlazeBurnerBlock.HeatLevel.FADING))
|
||||
if (checkState.has(BlazeBurnerBlock.HEAT_LEVEL) && !checkState.get(BlazeBurnerBlock.HEAT_LEVEL)
|
||||
.isAtLeast(BlazeBurnerBlock.HeatLevel.FADING))
|
||||
return false;
|
||||
|
||||
if (checkState.has(BlockStateProperties.LIT) && !checkState.get(BlockStateProperties.LIT))
|
||||
|
|
|
@ -38,26 +38,30 @@ public class NozzleTileEntity extends SmartTileEntity {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
|
||||
}
|
||||
public void addBehaviours(List<TileEntityBehaviour> behaviours) {}
|
||||
|
||||
@Override
|
||||
public CompoundNBT writeToClient(CompoundNBT compound) {
|
||||
protected void write(CompoundNBT compound, boolean clientPacket) {
|
||||
super.write(compound, clientPacket);
|
||||
if (!clientPacket)
|
||||
return;
|
||||
compound.putFloat("Range", range);
|
||||
compound.putBoolean("Pushing", pushing);
|
||||
return super.writeToClient(compound);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void readClientUpdate(CompoundNBT tag) {
|
||||
range = tag.getFloat("Range");
|
||||
pushing = tag.getBoolean("Pushing");
|
||||
super.readClientUpdate(tag);
|
||||
protected void read(CompoundNBT compound, boolean clientPacket) {
|
||||
super.read(compound, clientPacket);
|
||||
if (!clientPacket)
|
||||
return;
|
||||
range = compound.getFloat("Range");
|
||||
pushing = compound.getBoolean("Pushing");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
fanPos = pos.offset(getBlockState().get(NozzleBlock.FACING).getOpposite());
|
||||
fanPos = pos.offset(getBlockState().get(NozzleBlock.FACING)
|
||||
.getOpposite());
|
||||
super.initialize();
|
||||
}
|
||||
|
||||
|
@ -72,24 +76,26 @@ public class NozzleTileEntity extends SmartTileEntity {
|
|||
Vec3d center = VecHelper.getCenterOf(pos);
|
||||
if (world.isRemote && range != 0) {
|
||||
if (world.rand.nextInt(
|
||||
MathHelper.clamp((AllConfigs.SERVER.kinetics.fanPushDistance.get() - (int) range), 1, 10)) == 0) {
|
||||
MathHelper.clamp((AllConfigs.SERVER.kinetics.fanPushDistance.get() - (int) range), 1, 10)) == 0) {
|
||||
Vec3d start = VecHelper.offsetRandomly(center, world.rand, pushing ? 1 : range / 2);
|
||||
Vec3d motion = center.subtract(start).normalize()
|
||||
.scale(MathHelper.clamp(range * (pushing ? .025f : 1f), 0, .5f) * (pushing ? -1 : 1));
|
||||
Vec3d motion = center.subtract(start)
|
||||
.normalize()
|
||||
.scale(MathHelper.clamp(range * (pushing ? .025f : 1f), 0, .5f) * (pushing ? -1 : 1));
|
||||
world.addParticle(ParticleTypes.POOF, start.x, start.y, start.z, motion.x, motion.y, motion.z);
|
||||
}
|
||||
}
|
||||
|
||||
for (Iterator<Entity> iterator = pushingEntities.iterator(); iterator.hasNext();) {
|
||||
Entity entity = iterator.next();
|
||||
Vec3d diff = entity.getPositionVec().subtract(center);
|
||||
Vec3d diff = entity.getPositionVec()
|
||||
.subtract(center);
|
||||
|
||||
if (!(entity instanceof PlayerEntity) && world.isRemote)
|
||||
continue;
|
||||
|
||||
double distance = diff.length();
|
||||
if (distance > range || entity.isSneaking()
|
||||
|| (entity instanceof PlayerEntity && ((PlayerEntity) entity).isCreative())) {
|
||||
|| (entity instanceof PlayerEntity && ((PlayerEntity) entity).isCreative())) {
|
||||
iterator.remove();
|
||||
continue;
|
||||
}
|
||||
|
@ -98,8 +104,10 @@ public class NozzleTileEntity extends SmartTileEntity {
|
|||
continue;
|
||||
|
||||
float factor = (entity instanceof ItemEntity) ? 1 / 128f : 1 / 32f;
|
||||
Vec3d pushVec = diff.normalize().scale((range - distance) * (pushing ? 1 : -1));
|
||||
entity.setMotion(entity.getMotion().add(pushVec.scale(factor)));
|
||||
Vec3d pushVec = diff.normalize()
|
||||
.scale((range - distance) * (pushing ? 1 : -1));
|
||||
entity.setMotion(entity.getMotion()
|
||||
.add(pushVec.scale(factor)));
|
||||
entity.fallDistance = 0;
|
||||
entity.velocityChanged = true;
|
||||
}
|
||||
|
@ -125,7 +133,8 @@ public class NozzleTileEntity extends SmartTileEntity {
|
|||
return 0;
|
||||
if (fan.getSpeed() == 0)
|
||||
return 0;
|
||||
pushing = fan.getAirFlowDirection() == fan.getBlockState().get(EncasedFanBlock.FACING);
|
||||
pushing = fan.getAirFlowDirection() == fan.getBlockState()
|
||||
.get(EncasedFanBlock.FACING);
|
||||
return fan.getMaxDistance();
|
||||
}
|
||||
|
||||
|
@ -140,11 +149,12 @@ public class NozzleTileEntity extends SmartTileEntity {
|
|||
AxisAlignedBB bb = new AxisAlignedBB(center, center).grow(range / 2f);
|
||||
|
||||
for (Entity entity : world.getEntitiesWithinAABB(Entity.class, bb)) {
|
||||
Vec3d diff = entity.getPositionVec().subtract(center);
|
||||
Vec3d diff = entity.getPositionVec()
|
||||
.subtract(center);
|
||||
|
||||
double distance = diff.length();
|
||||
if (distance > range || entity.isSneaking()
|
||||
|| (entity instanceof PlayerEntity && ((PlayerEntity) entity).isCreative())) {
|
||||
|| (entity instanceof PlayerEntity && ((PlayerEntity) entity).isCreative())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -164,7 +174,7 @@ public class NozzleTileEntity extends SmartTileEntity {
|
|||
continue;
|
||||
iterator.remove();
|
||||
}
|
||||
|
||||
|
||||
if (!pushing && pushingEntities.size() > 256 && !world.isRemote) {
|
||||
world.createExplosion(null, center.x, center.y, center.z, 2, Mode.NONE);
|
||||
for (Iterator<Entity> iterator = pushingEntities.iterator(); iterator.hasNext();) {
|
||||
|
@ -178,8 +188,9 @@ public class NozzleTileEntity extends SmartTileEntity {
|
|||
|
||||
private boolean canSee(Entity entity) {
|
||||
RayTraceContext context = new RayTraceContext(entity.getPositionVec(), VecHelper.getCenterOf(pos),
|
||||
BlockMode.COLLIDER, FluidMode.NONE, entity);
|
||||
return pos.equals(world.rayTraceBlocks(context).getPos());
|
||||
BlockMode.COLLIDER, FluidMode.NONE, entity);
|
||||
return pos.equals(world.rayTraceBlocks(context)
|
||||
.getPos());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -53,30 +53,21 @@ public class FlywheelTileEntity extends GeneratingKineticTileEntity {
|
|||
}
|
||||
|
||||
@Override
|
||||
public CompoundNBT writeToClient(CompoundNBT compound) {
|
||||
return super.writeToClient(compound);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readClientUpdate(CompoundNBT tag) {
|
||||
super.readClientUpdate(tag);
|
||||
visualSpeed.withSpeed(1 / 32f).target(getGeneratedSpeed());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundNBT write(CompoundNBT compound) {
|
||||
public void write(CompoundNBT compound, boolean clientPacket) {
|
||||
compound.putFloat("GeneratedSpeed", generatedSpeed);
|
||||
compound.putFloat("GeneratedCapacity", generatedCapacity);
|
||||
compound.putInt("Cooldown", stoppingCooldown);
|
||||
return super.write(compound);
|
||||
super.write(compound, clientPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(CompoundNBT compound) {
|
||||
protected void read(CompoundNBT compound, boolean clientPacket) {
|
||||
generatedSpeed = compound.getFloat("GeneratedSpeed");
|
||||
generatedCapacity = compound.getFloat("GeneratedCapacity");
|
||||
stoppingCooldown = compound.getInt("Cooldown");
|
||||
super.read(compound);
|
||||
super.read(compound, clientPacket);
|
||||
if (clientPacket)
|
||||
visualSpeed.withSpeed(1 / 32f).target(getGeneratedSpeed());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -116,19 +116,19 @@ public class MillstoneTileEntity extends KineticTileEntity {
|
|||
}
|
||||
|
||||
@Override
|
||||
public CompoundNBT write(CompoundNBT compound) {
|
||||
public void write(CompoundNBT compound, boolean clientPacket) {
|
||||
compound.putInt("Timer", timer);
|
||||
compound.put("InputInventory", inputInv.serializeNBT());
|
||||
compound.put("OutputInventory", outputInv.serializeNBT());
|
||||
return super.write(compound);
|
||||
super.write(compound, clientPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(CompoundNBT compound) {
|
||||
protected void read(CompoundNBT compound, boolean clientPacket) {
|
||||
timer = compound.getInt("Timer");
|
||||
inputInv.deserializeNBT(compound.getCompound("InputInventory"));
|
||||
outputInv.deserializeNBT(compound.getCompound("OutputInventory"));
|
||||
super.read(compound);
|
||||
super.read(compound, clientPacket);
|
||||
}
|
||||
|
||||
public int getProcessingSpeed() {
|
||||
|
|
|
@ -109,17 +109,17 @@ public class MechanicalMixerTileEntity extends BasinOperatingTileEntity {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void read(CompoundNBT compound) {
|
||||
protected void read(CompoundNBT compound, boolean clientPacket) {
|
||||
running = compound.getBoolean("Running");
|
||||
runningTicks = compound.getInt("Ticks");
|
||||
super.read(compound);
|
||||
super.read(compound, clientPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundNBT write(CompoundNBT compound) {
|
||||
public void write(CompoundNBT compound, boolean clientPacket) {
|
||||
compound.putBoolean("Running", running);
|
||||
compound.putInt("Ticks", runningTicks);
|
||||
return super.write(compound);
|
||||
super.write(compound, clientPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -15,6 +15,7 @@ import com.simibubi.create.foundation.advancement.AllTriggers;
|
|||
import com.simibubi.create.foundation.item.ItemHelper;
|
||||
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||
import com.simibubi.create.foundation.tileEntity.behaviour.belt.BeltProcessingBehaviour;
|
||||
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
|
@ -25,7 +26,6 @@ import net.minecraft.item.crafting.ICraftingRecipe;
|
|||
import net.minecraft.item.crafting.IRecipe;
|
||||
import net.minecraft.item.crafting.Ingredient;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.nbt.ListNBT;
|
||||
import net.minecraft.particles.ItemParticleData;
|
||||
import net.minecraft.particles.ParticleTypes;
|
||||
import net.minecraft.tileentity.TileEntityType;
|
||||
|
@ -85,37 +85,30 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void read(CompoundNBT compound) {
|
||||
protected void read(CompoundNBT compound, boolean clientPacket) {
|
||||
running = compound.getBoolean("Running");
|
||||
mode = Mode.values()[compound.getInt("Mode")];
|
||||
finished = compound.getBoolean("Finished");
|
||||
runningTicks = compound.getInt("Ticks");
|
||||
super.read(compound);
|
||||
super.read(compound, clientPacket);
|
||||
|
||||
if (clientPacket) {
|
||||
NBTHelper.iterateCompoundList(compound.getList("ParticleItems", NBT.TAG_COMPOUND),
|
||||
c -> pressedItems.add(ItemStack.read(c)));
|
||||
spawnParticles();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundNBT write(CompoundNBT compound) {
|
||||
public void write(CompoundNBT compound, boolean clientPacket) {
|
||||
compound.putBoolean("Running", running);
|
||||
compound.putInt("Mode", mode.ordinal());
|
||||
compound.putBoolean("Finished", finished);
|
||||
compound.putInt("Ticks", runningTicks);
|
||||
return super.write(compound);
|
||||
}
|
||||
super.write(compound, clientPacket);
|
||||
|
||||
@Override
|
||||
public CompoundNBT writeToClient(CompoundNBT tag) {
|
||||
ListNBT particleItems = new ListNBT();
|
||||
pressedItems.forEach(stack -> particleItems.add(stack.serializeNBT()));
|
||||
tag.put("ParticleItems", particleItems);
|
||||
return super.writeToClient(tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readClientUpdate(CompoundNBT tag) {
|
||||
super.readClientUpdate(tag);
|
||||
ListNBT particleItems = tag.getList("ParticleItems", NBT.TAG_COMPOUND);
|
||||
particleItems.forEach(nbt -> pressedItems.add(ItemStack.read((CompoundNBT) nbt)));
|
||||
spawnParticles();
|
||||
if (clientPacket)
|
||||
compound.put("ParticleItems", NBTHelper.writeCompoundList(pressedItems, ItemStack::serializeNBT));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -301,7 +294,8 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity {
|
|||
|
||||
CombinedItemFluidList remaining = new CombinedItemFluidList();
|
||||
inputs.forEachItemStack(stack -> remaining.add(stack.copy()));
|
||||
basinFluidInv.ifPresent(fluidInv -> ((CombinedFluidHandler) fluidInv).forEachTank(fluidStack -> remaining.add(fluidStack.copy())));
|
||||
basinFluidInv.ifPresent(
|
||||
fluidInv -> ((CombinedFluidHandler) fluidInv).forEachTank(fluidStack -> remaining.add(fluidStack.copy())));
|
||||
|
||||
Ingredients: for (Ingredient ingredient : ingredients) {
|
||||
for (ItemStack stack : remaining.getItemStacks()) {
|
||||
|
|
|
@ -94,15 +94,15 @@ public class SawTileEntity extends BlockBreakingKineticTileEntity {
|
|||
}
|
||||
|
||||
@Override
|
||||
public CompoundNBT write(CompoundNBT compound) {
|
||||
public void write(CompoundNBT compound, boolean clientPacket) {
|
||||
compound.put("Inventory", inventory.serializeNBT());
|
||||
compound.putInt("RecipeIndex", recipeIndex);
|
||||
return super.write(compound);
|
||||
super.write(compound, clientPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(CompoundNBT compound) {
|
||||
super.read(compound);
|
||||
protected void read(CompoundNBT compound, boolean clientPacket) {
|
||||
super.read(compound, clientPacket);
|
||||
inventory.deserializeNBT(compound.getCompound("Inventory"));
|
||||
recipeIndex = compound.getInt("RecipeIndex");
|
||||
}
|
||||
|
|
|
@ -465,7 +465,7 @@ public abstract class Contraption {
|
|||
renderOrder.add(0, info.pos);
|
||||
CompoundNBT tag = info.nbt;
|
||||
MovementBehaviour movementBehaviour = AllMovementBehaviours.getMovementBehaviour(block);
|
||||
if (tag == null || movementBehaviour == null || movementBehaviour.hasSpecialMovementRenderer())
|
||||
if (tag == null || (movementBehaviour != null && movementBehaviour.hasSpecialMovementRenderer()))
|
||||
return;
|
||||
|
||||
tag.putInt("x", info.pos.getX());
|
||||
|
@ -797,7 +797,7 @@ public abstract class Contraption {
|
|||
|
||||
Vec3d vec = new Vec3d(Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis)
|
||||
.getDirectionVec());
|
||||
Vec3d planeByNormal = VecHelper.planeByNormal(vec);
|
||||
Vec3d planeByNormal = VecHelper.axisAlingedPlaneOf(vec);
|
||||
Vec3d min = vec.mul(bb.minX, bb.minY, bb.minZ)
|
||||
.add(planeByNormal.scale(-maxDiff));
|
||||
Vec3d max = vec.mul(bb.maxX, bb.maxY, bb.maxZ)
|
||||
|
|
|
@ -476,7 +476,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
|||
BearingContraption bc = (BearingContraption) getContraption();
|
||||
Direction facing = bc.getFacing();
|
||||
Vec3d activeAreaOffset = actor.getActiveAreaOffset(context);
|
||||
if (activeAreaOffset.mul(VecHelper.planeByNormal(new Vec3d(facing.getDirectionVec())))
|
||||
if (activeAreaOffset.mul(VecHelper.axisAlingedPlaneOf(new Vec3d(facing.getDirectionVec())))
|
||||
.equals(Vec3d.ZERO)) {
|
||||
if (VecHelper.onSameAxis(blockInfo.pos, BlockPos.ZERO, facing.getAxis())) {
|
||||
context.motion = new Vec3d(facing.getDirectionVec()).scale(facing.getAxis()
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package com.simibubi.create.content.contraptions.components.structureMovement;
|
||||
import org.apache.commons.lang3.mutable.MutableObject;
|
||||
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionEntity;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.sync.ContraptionInteractionPacket;
|
||||
import com.simibubi.create.foundation.networking.AllPackets;
|
||||
import com.simibubi.create.foundation.utility.RaycastHelper;
|
|
@ -227,26 +227,26 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe
|
|||
}
|
||||
|
||||
@Override
|
||||
public CompoundNBT write(CompoundNBT tag) {
|
||||
tag.putBoolean("Running", running);
|
||||
tag.putFloat("HourAngle", hourAngle);
|
||||
tag.putFloat("MinuteAngle", minuteAngle);
|
||||
return super.write(tag);
|
||||
public void write(CompoundNBT compound, boolean clientPacket) {
|
||||
compound.putBoolean("Running", running);
|
||||
compound.putFloat("HourAngle", hourAngle);
|
||||
compound.putFloat("MinuteAngle", minuteAngle);
|
||||
super.write(compound, clientPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(CompoundNBT tag) {
|
||||
running = tag.getBoolean("Running");
|
||||
hourAngle = tag.getFloat("HourAngle");
|
||||
minuteAngle = tag.getFloat("MinuteAngle");
|
||||
super.read(tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readClientUpdate(CompoundNBT tag) {
|
||||
protected void read(CompoundNBT compound, boolean clientPacket) {
|
||||
float hourAngleBefore = hourAngle;
|
||||
float minuteAngleBefore = minuteAngle;
|
||||
super.readClientUpdate(tag);
|
||||
|
||||
running = compound.getBoolean("Running");
|
||||
hourAngle = compound.getFloat("HourAngle");
|
||||
minuteAngle = compound.getFloat("MinuteAngle");
|
||||
super.read(compound, clientPacket);
|
||||
|
||||
if (!clientPacket)
|
||||
return;
|
||||
|
||||
if (running) {
|
||||
clientHourAngleDiff = AngleHelper.getShortestAngleDiff(hourAngleBefore, hourAngle);
|
||||
clientMinuteAngleDiff = AngleHelper.getShortestAngleDiff(minuteAngleBefore, minuteAngle);
|
||||
|
|
|
@ -102,27 +102,25 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
|
|||
}
|
||||
|
||||
@Override
|
||||
public CompoundNBT write(CompoundNBT tag) {
|
||||
tag.putBoolean("Running", running);
|
||||
tag.putBoolean("Windmill", isWindmill);
|
||||
tag.putFloat("Angle", angle);
|
||||
tag.putFloat("LastGenerated", lastGeneratedSpeed);
|
||||
return super.write(tag);
|
||||
public void write(CompoundNBT compound, boolean clientPacket) {
|
||||
compound.putBoolean("Running", running);
|
||||
compound.putBoolean("Windmill", isWindmill);
|
||||
compound.putFloat("Angle", angle);
|
||||
compound.putFloat("LastGenerated", lastGeneratedSpeed);
|
||||
super.write(compound, clientPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(CompoundNBT tag) {
|
||||
running = tag.getBoolean("Running");
|
||||
isWindmill = tag.getBoolean("Windmill");
|
||||
angle = tag.getFloat("Angle");
|
||||
lastGeneratedSpeed = tag.getFloat("LastGenerated");
|
||||
super.read(tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readClientUpdate(CompoundNBT tag) {
|
||||
protected void read(CompoundNBT compound, boolean clientPacket) {
|
||||
float angleBefore = angle;
|
||||
super.readClientUpdate(tag);
|
||||
running = compound.getBoolean("Running");
|
||||
isWindmill = compound.getBoolean("Windmill");
|
||||
angle = compound.getFloat("Angle");
|
||||
lastGeneratedSpeed = compound.getFloat("LastGenerated");
|
||||
super.read(compound, clientPacket);
|
||||
|
||||
if (!clientPacket)
|
||||
return;
|
||||
if (running) {
|
||||
clientAngleDiff = AngleHelper.getShortestAngleDiff(angleBefore, angle);
|
||||
angle = angleBefore;
|
||||
|
|
|
@ -81,7 +81,7 @@ public class SuperGlueItem extends Item {
|
|||
@OnlyIn(Dist.CLIENT)
|
||||
public static void spawnParticles(World world, BlockPos pos, Direction direction, boolean fullBlock) {
|
||||
Vec3d vec = new Vec3d(direction.getDirectionVec());
|
||||
Vec3d plane = VecHelper.planeByNormal(vec);
|
||||
Vec3d plane = VecHelper.axisAlingedPlaneOf(vec);
|
||||
Vec3d facePos = VecHelper.getCenterOf(pos)
|
||||
.add(vec.scale(.5f));
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import com.mojang.blaze3d.vertex.IVertexBuilder;
|
|||
import com.simibubi.create.AllItems;
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||
import com.simibubi.create.foundation.utility.MatrixStacker;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
@ -63,7 +64,9 @@ public class SuperGlueRenderer extends EntityRenderer<SuperGlueEntity> {
|
|||
Direction face = entity.getFacingDirection();
|
||||
|
||||
ms.push();
|
||||
AngleHelper.applyRotation(face, ms);
|
||||
MatrixStacker.of(ms)
|
||||
.rotateY(AngleHelper.horizontalAngle(face))
|
||||
.rotateX(AngleHelper.verticalAngle(face));
|
||||
Entry peek = ms.peek();
|
||||
|
||||
Vec3d[][] quads = { quad1, quad2 };
|
||||
|
@ -87,7 +90,7 @@ public class SuperGlueRenderer extends EntityRenderer<SuperGlueEntity> {
|
|||
Vec3d diff = new Vec3d(Direction.SOUTH.getDirectionVec());
|
||||
Vec3d extension = diff.normalize()
|
||||
.scale(1 / 32f - 1 / 128f);
|
||||
Vec3d plane = VecHelper.planeByNormal(diff);
|
||||
Vec3d plane = VecHelper.axisAlingedPlaneOf(diff);
|
||||
Axis axis = Direction.getFacingFromVector(diff.x, diff.y, diff.z)
|
||||
.getAxis();
|
||||
|
||||
|
|
|
@ -145,50 +145,38 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity impleme
|
|||
}
|
||||
|
||||
@Override
|
||||
public CompoundNBT write(CompoundNBT tag) {
|
||||
tag.putBoolean("Running", running);
|
||||
tag.putBoolean("Waiting", waitingForSpeedChange);
|
||||
tag.putFloat("Offset", offset);
|
||||
return super.write(tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundNBT writeToClient(CompoundNBT compound) {
|
||||
if (forceMove) {
|
||||
protected void write(CompoundNBT compound, boolean clientPacket) {
|
||||
compound.putBoolean("Running", running);
|
||||
compound.putBoolean("Waiting", waitingForSpeedChange);
|
||||
compound.putFloat("Offset", offset);
|
||||
super.write(compound, clientPacket);
|
||||
|
||||
if (clientPacket && forceMove) {
|
||||
compound.putBoolean("ForceMovement", forceMove);
|
||||
forceMove = false;
|
||||
}
|
||||
return super.writeToClient(compound);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(CompoundNBT tag) {
|
||||
running = tag.getBoolean("Running");
|
||||
waitingForSpeedChange = tag.getBoolean("Waiting");
|
||||
offset = tag.getFloat("Offset");
|
||||
super.read(tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readClientUpdate(CompoundNBT tag) {
|
||||
boolean forceMovement = tag.contains("ForceMovement");
|
||||
protected void read(CompoundNBT compound, boolean clientPacket) {
|
||||
boolean forceMovement = compound.contains("ForceMovement");
|
||||
float offsetBefore = offset;
|
||||
super.readClientUpdate(tag);
|
||||
|
||||
if (forceMovement) {
|
||||
if (movedContraption != null) {
|
||||
applyContraptionPosition();
|
||||
}
|
||||
} else {
|
||||
if (running) {
|
||||
clientOffsetDiff = offset - offsetBefore;
|
||||
offset = offsetBefore;
|
||||
}
|
||||
running = compound.getBoolean("Running");
|
||||
waitingForSpeedChange = compound.getBoolean("Waiting");
|
||||
offset = compound.getFloat("Offset");
|
||||
super.read(compound, clientPacket);
|
||||
|
||||
if (!clientPacket)
|
||||
return;
|
||||
if (forceMovement)
|
||||
applyContraptionPosition();
|
||||
else if (running) {
|
||||
clientOffsetDiff = offset - offsetBefore;
|
||||
offset = offsetBefore;
|
||||
}
|
||||
|
||||
if (!running)
|
||||
movedContraption = null;
|
||||
|
||||
}
|
||||
|
||||
public abstract void disassemble();
|
||||
|
|
|
@ -29,15 +29,15 @@ public class MechanicalPistonTileEntity extends LinearActuatorTileEntity {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void read(CompoundNBT tag) {
|
||||
extensionLength = tag.getInt("ExtensionLength");
|
||||
super.read(tag);
|
||||
protected void read(CompoundNBT compound, boolean clientPacket) {
|
||||
extensionLength = compound.getInt("ExtensionLength");
|
||||
super.read(compound, clientPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundNBT write(CompoundNBT tag) {
|
||||
protected void write(CompoundNBT tag, boolean clientPacket) {
|
||||
tag.putInt("ExtensionLength", extensionLength);
|
||||
return super.write(tag);
|
||||
super.write(tag, clientPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -8,6 +8,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.pis
|
|||
import com.simibubi.create.foundation.config.AllConfigs;
|
||||
import com.simibubi.create.foundation.tileEntity.behaviour.CenteredSideValueBoxTransform;
|
||||
import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.IWaterLoggable;
|
||||
|
@ -168,15 +169,15 @@ public class PulleyTileEntity extends LinearActuatorTileEntity {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void read(CompoundNBT tag) {
|
||||
initialOffset = tag.getInt("InitialOffset");
|
||||
super.read(tag);
|
||||
protected void read(CompoundNBT compound, boolean clientPacket) {
|
||||
initialOffset = compound.getInt("InitialOffset");
|
||||
super.read(compound, clientPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundNBT write(CompoundNBT tag) {
|
||||
tag.putInt("InitialOffset", initialOffset);
|
||||
return super.write(tag);
|
||||
public void write(CompoundNBT compound, boolean clientPacket) {
|
||||
compound.putInt("InitialOffset", initialOffset);
|
||||
super.write(compound, clientPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -24,8 +24,8 @@ public class WaterWheelTileEntity extends GeneratingKineticTileEntity {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void read(CompoundNBT compound) {
|
||||
super.read(compound);
|
||||
protected void read(CompoundNBT compound, boolean clientPacket) {
|
||||
super.read(compound, clientPacket);
|
||||
if (compound.contains("Flows")) {
|
||||
for (Direction d : Direction.values())
|
||||
setFlow(d, compound.getCompound("Flows")
|
||||
|
@ -39,13 +39,13 @@ public class WaterWheelTileEntity extends GeneratingKineticTileEntity {
|
|||
}
|
||||
|
||||
@Override
|
||||
public CompoundNBT write(CompoundNBT compound) {
|
||||
public void write(CompoundNBT compound, boolean clientPacket) {
|
||||
CompoundNBT flows = new CompoundNBT();
|
||||
for (Direction d : Direction.values())
|
||||
flows.putFloat(d.getName(), this.flows.get(d));
|
||||
compound.put("Flows", flows);
|
||||
|
||||
return super.write(compound);
|
||||
super.write(compound, clientPacket);
|
||||
}
|
||||
|
||||
public void setFlow(Direction direction, float speed) {
|
||||
|
|
|
@ -87,17 +87,20 @@ public class CombinedFluidHandler implements IFluidHandler {
|
|||
@Nonnull
|
||||
@Override
|
||||
public FluidStack drain(int maxDrain, FluidAction action) {
|
||||
|
||||
FluidStack stack = new FluidStack(tanks[0].getFluid(), 0);
|
||||
|
||||
for (int i = 0; i < tanks.length; i++) {
|
||||
if (tanks[i].isFluidEqual(stack)) {
|
||||
if (stack.isEmpty() || tanks[i].isFluidEqual(stack)) {
|
||||
int newDrainAmount = MathHelper.clamp(stack.getAmount() + tanks[i].getAmount(), 0, maxDrain);
|
||||
if (action == FluidAction.EXECUTE) {
|
||||
tanks[i].shrink(newDrainAmount - stack.getAmount());
|
||||
if (tanks[i].isEmpty())
|
||||
tanks[i] = FluidStack.EMPTY;
|
||||
}
|
||||
if (stack.isEmpty())
|
||||
stack = tanks[i].copy();
|
||||
if (stack.isEmpty())
|
||||
continue;
|
||||
stack.setAmount(newDrainAmount);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,355 @@
|
|||
package com.simibubi.create.content.contraptions.fluids;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.simibubi.create.foundation.utility.BlockFace;
|
||||
import com.simibubi.create.foundation.utility.Pair;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IWorld;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
|
||||
import net.minecraftforge.fluids.capability.IFluidHandler;
|
||||
|
||||
public class FluidNetwork {
|
||||
|
||||
BlockFace pumpLocation;
|
||||
Map<BlockPos, Pair<Integer, Map<Direction, Boolean>>> pipeGraph;
|
||||
List<FluidNetworkFlow> flows;
|
||||
Set<FluidNetworkEndpoint> targets;
|
||||
Set<BlockFace> rangeEndpoints;
|
||||
Map<BlockFace, FluidStack> previousFlow;
|
||||
|
||||
boolean connectToPumps;
|
||||
int waitForUnloadedNetwork;
|
||||
|
||||
public FluidNetwork() {
|
||||
pipeGraph = new HashMap<>();
|
||||
flows = new ArrayList<>();
|
||||
targets = new HashSet<>();
|
||||
rangeEndpoints = new HashSet<>();
|
||||
previousFlow = new HashMap<>();
|
||||
}
|
||||
|
||||
public boolean hasEndpoints() {
|
||||
for (FluidNetworkFlow pipeFlow : flows)
|
||||
if (pipeFlow.hasValidTargets())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public Collection<FluidNetworkEndpoint> getEndpoints(boolean pulling) {
|
||||
if (!pulling) {
|
||||
for (FluidNetworkFlow pipeFlow : flows)
|
||||
return pipeFlow.outputEndpoints;
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
List<FluidNetworkEndpoint> list = new ArrayList<>();
|
||||
for (FluidNetworkFlow pipeFlow : flows) {
|
||||
if (!pipeFlow.hasValidTargets())
|
||||
continue;
|
||||
list.add(pipeFlow.source);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public void tick(IWorld world, PumpTileEntity pumpTE) {
|
||||
if (connectToPumps) {
|
||||
connectToOtherFNs(world, pumpTE);
|
||||
connectToPumps = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void tickFlows(IWorld world, PumpTileEntity pumpTE, boolean pulling, float speed) {
|
||||
if (connectToPumps)
|
||||
return;
|
||||
initFlows(pumpTE, pulling);
|
||||
previousFlow.clear();
|
||||
flows.forEach(ep -> ep.tick(world, speed));
|
||||
}
|
||||
|
||||
private void initFlows(PumpTileEntity pumpTE, boolean pulling) {
|
||||
if (targets.isEmpty())
|
||||
return;
|
||||
if (!flows.isEmpty())
|
||||
return;
|
||||
World world = pumpTE.getWorld();
|
||||
if (pulling) {
|
||||
targets.forEach(ne -> flows.add(new FluidNetworkFlow(this, ne, world, pulling)));
|
||||
} else {
|
||||
PumpEndpoint pumpEndpoint = new PumpEndpoint(pumpLocation.getOpposite(), pumpTE);
|
||||
flows.add(new FluidNetworkFlow(this, pumpEndpoint, world, pulling));
|
||||
}
|
||||
}
|
||||
|
||||
public void connectToOtherFNs(IWorld world, PumpTileEntity pump) {
|
||||
List<Pair<Integer, BlockPos>> frontier = new ArrayList<>();
|
||||
Set<BlockPos> visited = new HashSet<>();
|
||||
int maxDistance = FluidPropagator.getPumpRange() * 2;
|
||||
frontier.add(Pair.of(-1, pumpLocation.getPos()));
|
||||
|
||||
while (!frontier.isEmpty()) {
|
||||
Pair<Integer, BlockPos> entry = frontier.remove(0);
|
||||
int distance = entry.getFirst();
|
||||
BlockPos currentPos = entry.getSecond();
|
||||
|
||||
if (!world.isAreaLoaded(currentPos, 0))
|
||||
continue;
|
||||
if (visited.contains(currentPos))
|
||||
continue;
|
||||
visited.add(currentPos);
|
||||
|
||||
List<Direction> connections;
|
||||
if (currentPos.equals(pumpLocation.getPos())) {
|
||||
connections = ImmutableList.of(pumpLocation.getFace());
|
||||
} else {
|
||||
BlockState currentState = world.getBlockState(currentPos);
|
||||
FluidPipeBehaviour pipe = FluidPropagator.getPipe(world, currentPos);
|
||||
if (pipe == null)
|
||||
continue;
|
||||
connections = FluidPropagator.getPipeConnections(currentState, pipe);
|
||||
}
|
||||
|
||||
for (Direction face : connections) {
|
||||
BlockFace blockFace = new BlockFace(currentPos, face);
|
||||
BlockPos connectedPos = blockFace.getConnectedPos();
|
||||
BlockState connectedState = world.getBlockState(connectedPos);
|
||||
|
||||
if (connectedPos.equals(pumpLocation.getPos()))
|
||||
continue;
|
||||
if (!world.isAreaLoaded(connectedPos, 0))
|
||||
continue;
|
||||
if (PumpBlock.isPump(connectedState) && connectedState.get(PumpBlock.FACING)
|
||||
.getAxis() == face.getAxis()) {
|
||||
TileEntity tileEntity = world.getTileEntity(connectedPos);
|
||||
if (tileEntity instanceof PumpTileEntity) {
|
||||
PumpTileEntity otherPump = (PumpTileEntity) tileEntity;
|
||||
if (otherPump.networks == null)
|
||||
continue;
|
||||
|
||||
otherPump.networks.forEach(fn -> {
|
||||
int nearest = Integer.MAX_VALUE;
|
||||
BlockFace argNearest = null;
|
||||
for (BlockFace pumpEndpoint : fn.rangeEndpoints) {
|
||||
if (pumpEndpoint.isEquivalent(pumpLocation)) {
|
||||
argNearest = pumpEndpoint;
|
||||
break;
|
||||
}
|
||||
Pair<Integer, Map<Direction, Boolean>> pair =
|
||||
pipeGraph.get(pumpEndpoint.getConnectedPos());
|
||||
if (pair == null)
|
||||
continue;
|
||||
Integer distanceFromPump = pair.getFirst();
|
||||
Map<Direction, Boolean> pipeConnections = pair.getSecond();
|
||||
|
||||
if (!pipeConnections.containsKey(pumpEndpoint.getOppositeFace()))
|
||||
continue;
|
||||
if (nearest <= distanceFromPump)
|
||||
continue;
|
||||
nearest = distanceFromPump;
|
||||
argNearest = pumpEndpoint;
|
||||
|
||||
}
|
||||
if (argNearest != null) {
|
||||
InterPumpEndpoint endpoint = new InterPumpEndpoint(world, argNearest.getOpposite(),
|
||||
pump, otherPump, pumpLocation, fn.pumpLocation);
|
||||
targets.add(endpoint);
|
||||
fn.targets.add(endpoint.opposite(world));
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (visited.contains(connectedPos))
|
||||
continue;
|
||||
if (distance > maxDistance)
|
||||
continue;
|
||||
FluidPipeBehaviour targetPipe = FluidPropagator.getPipe(world, connectedPos);
|
||||
if (targetPipe == null)
|
||||
continue;
|
||||
if (targetPipe.isConnectedTo(connectedState, face.getOpposite()))
|
||||
frontier.add(Pair.of(distance + 1, connectedPos));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void assemble(IWorld world, PumpTileEntity pumpTE, BlockFace pumpLocation) {
|
||||
Map<BlockFace, OpenEndedPipe> openEnds = pumpTE.getOpenEnds(pumpLocation.getFace());
|
||||
openEnds.values()
|
||||
.forEach(OpenEndedPipe::markStale);
|
||||
|
||||
this.pumpLocation = pumpLocation;
|
||||
if (!collectEndpoint(world, pumpLocation, openEnds, 0)) {
|
||||
|
||||
List<Pair<Integer, BlockPos>> frontier = new ArrayList<>();
|
||||
Set<BlockPos> visited = new HashSet<>();
|
||||
int maxDistance = FluidPropagator.getPumpRange();
|
||||
frontier.add(Pair.of(0, pumpLocation.getConnectedPos()));
|
||||
|
||||
while (!frontier.isEmpty()) {
|
||||
Pair<Integer, BlockPos> entry = frontier.remove(0);
|
||||
int distance = entry.getFirst();
|
||||
BlockPos currentPos = entry.getSecond();
|
||||
|
||||
if (!world.isAreaLoaded(currentPos, 0))
|
||||
continue;
|
||||
if (visited.contains(currentPos))
|
||||
continue;
|
||||
visited.add(currentPos);
|
||||
BlockState currentState = world.getBlockState(currentPos);
|
||||
FluidPipeBehaviour pipe = FluidPropagator.getPipe(world, currentPos);
|
||||
if (pipe == null)
|
||||
continue;
|
||||
|
||||
for (Direction face : FluidPropagator.getPipeConnections(currentState, pipe)) {
|
||||
BlockFace blockFace = new BlockFace(currentPos, face);
|
||||
BlockPos connectedPos = blockFace.getConnectedPos();
|
||||
|
||||
if (connectedPos.equals(pumpLocation.getPos())) {
|
||||
addEntry(blockFace.getPos(), blockFace.getFace(), true, distance);
|
||||
continue;
|
||||
}
|
||||
if (!world.isAreaLoaded(connectedPos, 0))
|
||||
continue;
|
||||
if (collectEndpoint(world, blockFace, openEnds, distance))
|
||||
continue;
|
||||
if (FluidPropagator.getPipe(world, connectedPos) == null)
|
||||
continue;
|
||||
if (visited.contains(connectedPos))
|
||||
continue;
|
||||
if (distance + 1 >= maxDistance) {
|
||||
rangeEndpoints.add(blockFace);
|
||||
addEntry(currentPos, face, false, distance);
|
||||
FluidPropagator.showBlockFace(blockFace)
|
||||
.lineWidth(1 / 8f)
|
||||
.colored(0xff0000);
|
||||
continue;
|
||||
}
|
||||
|
||||
addConnection(connectedPos, currentPos, face.getOpposite(), distance);
|
||||
frontier.add(Pair.of(distance + 1, connectedPos));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Set<BlockFace> staleEnds = new HashSet<>();
|
||||
openEnds.entrySet()
|
||||
.forEach(e -> {
|
||||
if (e.getValue()
|
||||
.isStale())
|
||||
staleEnds.add(e.getKey());
|
||||
});
|
||||
staleEnds.forEach(openEnds::remove);
|
||||
|
||||
connectToPumps = true;
|
||||
}
|
||||
|
||||
private FluidNetworkEndpoint reuseOrCreateOpenEnd(IWorld world, Map<BlockFace, OpenEndedPipe> openEnds,
|
||||
BlockFace toCreate) {
|
||||
OpenEndedPipe openEndedPipe = null;
|
||||
if (openEnds.containsKey(toCreate)) {
|
||||
openEndedPipe = openEnds.get(toCreate);
|
||||
openEndedPipe.unmarkStale();
|
||||
} else {
|
||||
openEndedPipe = new OpenEndedPipe(toCreate);
|
||||
openEnds.put(toCreate, openEndedPipe);
|
||||
}
|
||||
return new FluidNetworkEndpoint(world, toCreate, openEndedPipe.getCapability());
|
||||
|
||||
}
|
||||
|
||||
private boolean collectEndpoint(IWorld world, BlockFace blockFace, Map<BlockFace, OpenEndedPipe> openEnds,
|
||||
int distance) {
|
||||
BlockPos connectedPos = blockFace.getConnectedPos();
|
||||
BlockState connectedState = world.getBlockState(connectedPos);
|
||||
|
||||
// other pipe, no endpoint
|
||||
FluidPipeBehaviour pipe = FluidPropagator.getPipe(world, connectedPos);
|
||||
if (pipe != null && pipe.isConnectedTo(connectedState, blockFace.getOppositeFace()))
|
||||
return false;
|
||||
TileEntity tileEntity = world.getTileEntity(connectedPos);
|
||||
|
||||
// fluid handler endpoint
|
||||
Direction face = blockFace.getFace();
|
||||
if (tileEntity != null) {
|
||||
LazyOptional<IFluidHandler> capability =
|
||||
tileEntity.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, face.getOpposite());
|
||||
if (capability.isPresent()) {
|
||||
targets.add(new FluidNetworkEndpoint(world, blockFace, capability));
|
||||
addEntry(blockFace.getPos(), face, false, distance);
|
||||
FluidPropagator.showBlockFace(blockFace)
|
||||
.colored(0x00b7c2)
|
||||
.lineWidth(1 / 8f);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// open endpoint
|
||||
if (PumpBlock.isPump(connectedState) && connectedState.get(PumpBlock.FACING)
|
||||
.getAxis() == face.getAxis()) {
|
||||
rangeEndpoints.add(blockFace);
|
||||
addEntry(blockFace.getPos(), face, false, distance);
|
||||
return true;
|
||||
}
|
||||
if (!FluidPropagator.isOpenEnd(world, blockFace.getPos(), face))
|
||||
return false;
|
||||
|
||||
targets.add(reuseOrCreateOpenEnd(world, openEnds, blockFace));
|
||||
addEntry(blockFace.getPos(), face, false, distance);
|
||||
FluidPropagator.showBlockFace(blockFace)
|
||||
.colored(0xb700c2)
|
||||
.lineWidth(1 / 8f);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void addConnection(BlockPos from, BlockPos to, Direction direction, int distance) {
|
||||
addEntry(from, direction, true, distance);
|
||||
addEntry(to, direction.getOpposite(), false, distance + 1);
|
||||
}
|
||||
|
||||
private void addEntry(BlockPos pos, Direction direction, boolean outbound, int distance) {
|
||||
if (!pipeGraph.containsKey(pos))
|
||||
pipeGraph.put(pos, Pair.of(distance, new HashMap<>()));
|
||||
pipeGraph.get(pos)
|
||||
.getSecond()
|
||||
.put(direction, outbound);
|
||||
}
|
||||
|
||||
public void reAssemble(IWorld world, PumpTileEntity pumpTE, BlockFace pumpLocation) {
|
||||
rangeEndpoints.clear();
|
||||
targets.clear();
|
||||
pipeGraph.clear();
|
||||
assemble(world, pumpTE, pumpLocation);
|
||||
}
|
||||
|
||||
public void remove(IWorld world) {
|
||||
clearFlows(world, false);
|
||||
}
|
||||
|
||||
public void clearFlows(IWorld world, boolean saveState) {
|
||||
for (FluidNetworkFlow networkFlow : flows) {
|
||||
if (!networkFlow.getFluidStack()
|
||||
.isEmpty())
|
||||
networkFlow.addToSkippedConnections(world);
|
||||
networkFlow.resetFlow(world);
|
||||
}
|
||||
flows.clear();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,168 @@
|
|||
package com.simibubi.create.content.contraptions.fluids;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
import com.simibubi.create.foundation.utility.BlockFace;
|
||||
import com.simibubi.create.foundation.utility.Couple;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
import com.simibubi.create.foundation.utility.Pair;
|
||||
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.world.IWorld;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
|
||||
import net.minecraftforge.fluids.capability.IFluidHandler;
|
||||
import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction;
|
||||
|
||||
class FluidNetworkEndpoint {
|
||||
BlockFace location;
|
||||
protected LazyOptional<IFluidHandler> handler;
|
||||
|
||||
public FluidNetworkEndpoint(IWorld world, BlockFace location, LazyOptional<IFluidHandler> handler) {
|
||||
this.location = location;
|
||||
this.handler = handler;
|
||||
this.handler.addListener($ -> onHandlerInvalidated(world));
|
||||
}
|
||||
|
||||
protected void onHandlerInvalidated(IWorld world) {
|
||||
IFluidHandler tank = handler.orElse(null);
|
||||
if (tank != null)
|
||||
return;
|
||||
TileEntity tileEntity = world.getTileEntity(location.getConnectedPos());
|
||||
if (tileEntity == null)
|
||||
return;
|
||||
LazyOptional<IFluidHandler> capability =
|
||||
tileEntity.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, location.getOppositeFace());
|
||||
if (capability.isPresent()) {
|
||||
handler = capability;
|
||||
handler.addListener($ -> onHandlerInvalidated(world));
|
||||
}
|
||||
}
|
||||
|
||||
public FluidStack provideFluid() {
|
||||
IFluidHandler tank = provideHandler().orElse(null);
|
||||
if (tank == null)
|
||||
return FluidStack.EMPTY;
|
||||
return tank.drain(1, FluidAction.SIMULATE);
|
||||
}
|
||||
|
||||
public LazyOptional<IFluidHandler> provideHandler() {
|
||||
return handler;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class PumpEndpoint extends FluidNetworkEndpoint {
|
||||
|
||||
PumpTileEntity pumpTE;
|
||||
|
||||
public PumpEndpoint(BlockFace location, PumpTileEntity pumpTE) {
|
||||
super(pumpTE.getWorld(), location, LazyOptional.empty());
|
||||
this.pumpTE = pumpTE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onHandlerInvalidated(IWorld world) {}
|
||||
|
||||
@Override
|
||||
public FluidStack provideFluid() {
|
||||
return pumpTE.providedFluid;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class InterPumpEndpoint extends FluidNetworkEndpoint {
|
||||
|
||||
Couple<Pair<BlockFace, WeakReference<PumpTileEntity>>> pumps;
|
||||
|
||||
private InterPumpEndpoint(IWorld world, BlockFace location, LazyOptional<IFluidHandler> handler) {
|
||||
super(world, location, handler);
|
||||
}
|
||||
|
||||
public InterPumpEndpoint(IWorld world, BlockFace location, PumpTileEntity source, PumpTileEntity interfaced,
|
||||
BlockFace sourcePos, BlockFace interfacedPos) {
|
||||
this(world, location, LazyOptional.empty());
|
||||
handler = LazyOptional.of(() -> new InterPumpFluidHandler(this));
|
||||
pumps = Couple.create(Pair.of(sourcePos, new WeakReference<>(source)),
|
||||
Pair.of(interfacedPos, new WeakReference<>(interfaced)));
|
||||
}
|
||||
|
||||
public InterPumpEndpoint opposite(IWorld world) {
|
||||
InterPumpEndpoint interPumpEndpoint = new InterPumpEndpoint(world, this.location.getOpposite(), handler);
|
||||
interPumpEndpoint.pumps = pumps.copy();
|
||||
return interPumpEndpoint;
|
||||
}
|
||||
|
||||
public Couple<Pair<BlockFace, WeakReference<PumpTileEntity>>> getPumps() {
|
||||
return pumps;
|
||||
}
|
||||
|
||||
public boolean isPulling(boolean first) {
|
||||
Pair<BlockFace, WeakReference<PumpTileEntity>> pair = getPumps().get(first);
|
||||
PumpTileEntity pumpTileEntity = pair.getSecond()
|
||||
.get();
|
||||
if (pumpTileEntity == null || pumpTileEntity.isRemoved())
|
||||
return false;
|
||||
return pumpTileEntity.isPullingOnSide(pumpTileEntity.isFront(pair.getFirst()
|
||||
.getFace()));
|
||||
}
|
||||
|
||||
public int getTransferSpeed(boolean first) {
|
||||
PumpTileEntity pumpTileEntity = getPumps().get(first)
|
||||
.getSecond()
|
||||
.get();
|
||||
if (pumpTileEntity == null || pumpTileEntity.isRemoved())
|
||||
return 0;
|
||||
return pumpTileEntity.getFluidTransferSpeed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LazyOptional<IFluidHandler> provideHandler() {
|
||||
if (isPulling(true) == isPulling(false))
|
||||
return LazyOptional.empty();
|
||||
if (getTransferSpeed(true) > getTransferSpeed(false))
|
||||
return LazyOptional.empty();
|
||||
return super.provideHandler();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FluidStack provideFluid() {
|
||||
if (!provideHandler().isPresent())
|
||||
return FluidStack.EMPTY;
|
||||
|
||||
Couple<Pair<BlockFace, WeakReference<PumpTileEntity>>> pumps = getPumps();
|
||||
for (boolean current : Iterate.trueAndFalse) {
|
||||
if (isPulling(current))
|
||||
continue;
|
||||
|
||||
Pair<BlockFace, WeakReference<PumpTileEntity>> pair = pumps.get(current);
|
||||
BlockFace blockFace = pair.getFirst();
|
||||
PumpTileEntity pumpTileEntity = pair.getSecond()
|
||||
.get();
|
||||
if (pumpTileEntity == null)
|
||||
continue;
|
||||
if (pumpTileEntity.networks == null)
|
||||
continue;
|
||||
FluidNetwork fluidNetwork = pumpTileEntity.networks.get(pumpTileEntity.isFront(blockFace.getFace()));
|
||||
for (FluidNetworkFlow fluidNetworkFlow : fluidNetwork.flows) {
|
||||
for (FluidNetworkEndpoint fne : fluidNetworkFlow.outputEndpoints) {
|
||||
if (!(fne instanceof InterPumpEndpoint))
|
||||
continue;
|
||||
InterPumpEndpoint ipe = (InterPumpEndpoint) fne;
|
||||
if (!ipe.location.isEquivalent(location))
|
||||
continue;
|
||||
|
||||
FluidStack heldFluid = fluidNetworkFlow.fluidStack;
|
||||
if (heldFluid.isEmpty())
|
||||
return heldFluid;
|
||||
FluidStack copy = heldFluid.copy();
|
||||
copy.setAmount(1);
|
||||
return heldFluid;
|
||||
}
|
||||
}
|
||||
}
|
||||
return FluidStack.EMPTY;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,304 @@
|
|||
package com.simibubi.create.content.contraptions.fluids;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||
import com.simibubi.create.foundation.utility.BlockFace;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IWorld;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
|
||||
class FluidNetworkFlow {
|
||||
|
||||
@FunctionalInterface
|
||||
static interface PipeFlowConsumer {
|
||||
void accept(FluidPipeBehaviour pipe, Direction face, boolean inbound);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private final FluidNetwork activePipeNetwork;
|
||||
FluidNetworkEndpoint source;
|
||||
FluidStack fluidStack;
|
||||
Set<BlockFace> flowPointers;
|
||||
|
||||
Set<FluidNetworkEndpoint> outputEndpoints;
|
||||
boolean pumpReached;
|
||||
|
||||
boolean pulling;
|
||||
float speed;
|
||||
|
||||
public FluidNetworkFlow(FluidNetwork activePipeNetwork, FluidNetworkEndpoint source, IWorld world,
|
||||
boolean pulling) {
|
||||
this.activePipeNetwork = activePipeNetwork;
|
||||
this.source = source;
|
||||
this.pulling = pulling;
|
||||
flowPointers = new HashSet<>();
|
||||
outputEndpoints = new HashSet<>();
|
||||
fluidStack = FluidStack.EMPTY;
|
||||
tick(world, 0);
|
||||
}
|
||||
|
||||
void resetFlow(IWorld world) {
|
||||
fluidStack = FluidStack.EMPTY;
|
||||
flowPointers.clear();
|
||||
outputEndpoints.clear();
|
||||
pumpReached = false;
|
||||
forEachPipeFlow(world, (pipe, face, inbound) -> pipe.removeFlow(this, face, inbound));
|
||||
}
|
||||
|
||||
void addToSkippedConnections(IWorld world) {
|
||||
forEachPipeFlow(world, (pipe, face, inbound) -> {
|
||||
if (!pipe.getFluid().isFluidEqual(fluidStack))
|
||||
return;
|
||||
BlockFace blockFace = new BlockFace(pipe.getPos(), face);
|
||||
this.activePipeNetwork.previousFlow.put(blockFace, pipe.getFluid());
|
||||
});
|
||||
}
|
||||
|
||||
void forEachPipeFlow(IWorld world, FluidNetworkFlow.PipeFlowConsumer consumer) {
|
||||
Set<BlockFace> flowPointers = new HashSet<>();
|
||||
flowPointers.add(getSource());
|
||||
|
||||
// Update all branches of this flow, and create new ones if necessary
|
||||
while (!flowPointers.isEmpty()) {
|
||||
List<BlockFace> toAdd = new ArrayList<>();
|
||||
for (Iterator<BlockFace> iterator = flowPointers.iterator(); iterator.hasNext();) {
|
||||
BlockFace flowPointer = iterator.next();
|
||||
BlockPos currentPos = flowPointer.getPos();
|
||||
FluidPipeBehaviour pipe = getPipeInTree(world, currentPos);
|
||||
if (pipe == null) {
|
||||
iterator.remove();
|
||||
continue;
|
||||
}
|
||||
Map<Direction, Boolean> directions = this.activePipeNetwork.pipeGraph.get(currentPos)
|
||||
.getSecond();
|
||||
for (Entry<Direction, Boolean> entry : directions.entrySet()) {
|
||||
boolean inbound = entry.getValue() != pulling;
|
||||
Direction face = entry.getKey();
|
||||
if (inbound && face != flowPointer.getFace())
|
||||
continue;
|
||||
consumer.accept(pipe, face, inbound);
|
||||
if (inbound)
|
||||
continue;
|
||||
toAdd.add(new BlockFace(currentPos.offset(face), face.getOpposite()));
|
||||
}
|
||||
iterator.remove();
|
||||
}
|
||||
flowPointers.addAll(toAdd);
|
||||
}
|
||||
}
|
||||
|
||||
void tick(IWorld world, float speed) {
|
||||
boolean skipping = speed == 0;
|
||||
Map<BlockFace, FluidStack> previousFlow = this.activePipeNetwork.previousFlow;
|
||||
if (skipping && previousFlow.isEmpty())
|
||||
return;
|
||||
|
||||
this.speed = speed;
|
||||
FluidStack provideFluid = source.provideFluid();
|
||||
if (!fluidStack.isEmpty() && !fluidStack.isFluidEqual(provideFluid)) {
|
||||
resetFlow(world);
|
||||
return;
|
||||
}
|
||||
|
||||
fluidStack = provideFluid;
|
||||
|
||||
// There is currently no unfinished flow being followed
|
||||
if (flowPointers.isEmpty()) {
|
||||
|
||||
// The fluid source has run out -> reset
|
||||
if (fluidStack.isEmpty()) {
|
||||
if (hasValidTargets())
|
||||
resetFlow(world);
|
||||
return;
|
||||
}
|
||||
|
||||
// Keep the flows if all is well
|
||||
if (hasValidTargets())
|
||||
return;
|
||||
|
||||
// Start a new flow from or towards the pump
|
||||
BlockFace source = getSource();
|
||||
if (tryConnectTo(world, source.getOpposite()))
|
||||
return;
|
||||
flowPointers.add(source);
|
||||
}
|
||||
|
||||
boolean skipped = false;
|
||||
Set<BlockFace> pausedPointers = new HashSet<>();
|
||||
|
||||
do {
|
||||
skipped = false;
|
||||
List<BlockFace> toAdd = null;
|
||||
|
||||
// Update all branches of this flow, and create new ones if necessary
|
||||
for (Iterator<BlockFace> iterator = flowPointers.iterator(); iterator.hasNext();) {
|
||||
BlockFace flowPointer = iterator.next();
|
||||
BlockPos currentPos = flowPointer.getPos();
|
||||
|
||||
if (pausedPointers.contains(flowPointer))
|
||||
continue;
|
||||
|
||||
FluidPipeBehaviour pipe = getPipeInTree(world, currentPos);
|
||||
if (pipe == null) {
|
||||
iterator.remove();
|
||||
continue;
|
||||
}
|
||||
|
||||
Map<Direction, Boolean> directions = this.activePipeNetwork.pipeGraph.get(currentPos)
|
||||
.getSecond();
|
||||
boolean inboundComplete = false;
|
||||
boolean allFlowsComplete = true;
|
||||
BlockState state = world.getBlockState(currentPos);
|
||||
|
||||
// First loop only inbound flows of a pipe to see if they have reached the
|
||||
// center
|
||||
for (boolean inboundPass : Iterate.trueAndFalse) {
|
||||
if (!inboundPass && !inboundComplete)
|
||||
break;
|
||||
|
||||
// For all connections of the pipe tree of the pump
|
||||
for (Entry<Direction, Boolean> entry : directions.entrySet()) {
|
||||
Boolean awayFromPump = entry.getValue();
|
||||
Direction direction = entry.getKey();
|
||||
boolean inbound = awayFromPump != pulling;
|
||||
|
||||
if (inboundPass && direction != flowPointer.getFace())
|
||||
continue;
|
||||
if (!inboundPass && inbound)
|
||||
continue;
|
||||
if (!pipe.canTransferToward(fluidStack, state, direction, inbound))
|
||||
continue;
|
||||
|
||||
BlockFace blockface = new BlockFace(currentPos, direction);
|
||||
|
||||
if (!pipe.hasStartedFlow(this, direction, inbound))
|
||||
pipe.addFlow(this, direction, inbound, false);
|
||||
if (skipping && canSkip(previousFlow, blockface)) {
|
||||
pipe.skipFlow(direction, inbound);
|
||||
FluidPropagator.showBlockFace(blockface)
|
||||
.colored(0x0)
|
||||
.lineWidth(1 / 8f);
|
||||
skipped = true;
|
||||
}
|
||||
|
||||
if (!pipe.hasCompletedFlow(direction, inbound)) {
|
||||
allFlowsComplete = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (inboundPass) {
|
||||
inboundComplete = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Outward pass, check if any target was reached
|
||||
tryConnectTo(world, blockface);
|
||||
}
|
||||
}
|
||||
|
||||
if (!allFlowsComplete && !skipping)
|
||||
continue;
|
||||
|
||||
// Create a new flow branch at each outward pipe connection
|
||||
for (Entry<Direction, Boolean> entry : directions.entrySet()) {
|
||||
if (entry.getValue() != pulling)
|
||||
continue;
|
||||
Direction face = entry.getKey();
|
||||
BlockFace addedBlockFace = new BlockFace(currentPos.offset(face), face.getOpposite());
|
||||
if (skipping && !canSkip(previousFlow, addedBlockFace)) {
|
||||
allFlowsComplete = false;
|
||||
continue;
|
||||
}
|
||||
if (toAdd == null)
|
||||
toAdd = new ArrayList<>();
|
||||
toAdd.add(addedBlockFace);
|
||||
}
|
||||
|
||||
if (!allFlowsComplete && skipping) {
|
||||
pausedPointers.add(flowPointer);
|
||||
continue;
|
||||
}
|
||||
|
||||
iterator.remove();
|
||||
|
||||
} // End of branch loop
|
||||
|
||||
if (toAdd != null)
|
||||
flowPointers.addAll(toAdd);
|
||||
|
||||
} while (skipping && skipped);
|
||||
}
|
||||
|
||||
private boolean canSkip(Map<BlockFace, FluidStack> previousFlow, BlockFace blockface) {
|
||||
return previousFlow.containsKey(blockface) && previousFlow.get(blockface)
|
||||
.isFluidEqual(fluidStack);
|
||||
}
|
||||
|
||||
private boolean tryConnectTo(IWorld world, BlockFace blockface) {
|
||||
// Pulling flow, target is the pump
|
||||
if (pulling) {
|
||||
if (!this.activePipeNetwork.pumpLocation.getOpposite()
|
||||
.equals(blockface))
|
||||
return false;
|
||||
pumpReached = true;
|
||||
TileEntity targetTE = world.getTileEntity(this.activePipeNetwork.pumpLocation.getPos());
|
||||
if (targetTE instanceof PumpTileEntity)
|
||||
((PumpTileEntity) targetTE).setProvidedFluid(fluidStack);
|
||||
FluidPropagator.showBlockFace(this.activePipeNetwork.pumpLocation)
|
||||
.colored(0x799351)
|
||||
.lineWidth(1 / 8f);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Pushing flow, targets are the endpoints
|
||||
for (FluidNetworkEndpoint networkEndpoint : this.activePipeNetwork.targets) {
|
||||
if (!networkEndpoint.location.isEquivalent(blockface))
|
||||
continue;
|
||||
outputEndpoints.add(networkEndpoint);
|
||||
FluidPropagator.showBlockFace(blockface)
|
||||
.colored(0x799351)
|
||||
.lineWidth(1 / 8f);
|
||||
return !(networkEndpoint instanceof InterPumpEndpoint);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private BlockFace getSource() {
|
||||
return pulling ? source.location : this.activePipeNetwork.pumpLocation.getOpposite();
|
||||
}
|
||||
|
||||
private FluidPipeBehaviour getPipeInTree(IWorld world, BlockPos currentPos) {
|
||||
if (!world.isAreaLoaded(currentPos, 0))
|
||||
return null;
|
||||
if (!this.activePipeNetwork.pipeGraph.containsKey(currentPos))
|
||||
return null;
|
||||
return TileEntityBehaviour.get(world, currentPos, FluidPipeBehaviour.TYPE);
|
||||
}
|
||||
|
||||
boolean hasValidTargets() {
|
||||
return pumpReached || !outputEndpoints.isEmpty();
|
||||
}
|
||||
|
||||
public float getSpeed() {
|
||||
return speed;
|
||||
}
|
||||
|
||||
public FluidStack getFluidStack() {
|
||||
return fluidStack;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package com.simibubi.create.content.contraptions.fluids;
|
||||
|
||||
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
|
||||
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||
import com.simibubi.create.foundation.tileEntity.behaviour.BehaviourType;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.ILightReader;
|
||||
|
||||
public class FluidPipeAttachmentBehaviour extends TileEntityBehaviour {
|
||||
|
||||
public static BehaviourType<FluidPipeAttachmentBehaviour> TYPE = new BehaviourType<>();
|
||||
|
||||
public AttachmentTypes getAttachment(ILightReader world, BlockPos pos, BlockState state, Direction direction) {
|
||||
if (!isPipeConnectedTowards(state, direction))
|
||||
return AttachmentTypes.NONE;
|
||||
|
||||
BlockPos offsetPos = pos.offset(direction);
|
||||
BlockState facingState = world.getBlockState(offsetPos);
|
||||
|
||||
if (facingState.getBlock() instanceof PumpBlock && facingState.get(PumpBlock.FACING)
|
||||
.getAxis() == direction.getAxis())
|
||||
return AttachmentTypes.NONE;
|
||||
|
||||
if (FluidPropagator.hasFluidCapability(facingState, world, offsetPos, direction))
|
||||
return AttachmentTypes.DRAIN;
|
||||
|
||||
return AttachmentTypes.RIM;
|
||||
}
|
||||
|
||||
public boolean isPipeConnectedTowards(BlockState state, Direction direction) {
|
||||
FluidPipeBehaviour fluidPipeBehaviour = TileEntityBehaviour.get(tileEntity, FluidPipeBehaviour.TYPE);
|
||||
if (fluidPipeBehaviour == null)
|
||||
return false;
|
||||
return fluidPipeBehaviour.isConnectedTo(state, direction);
|
||||
}
|
||||
|
||||
public static enum AttachmentTypes {
|
||||
NONE, RIM, DRAIN;
|
||||
|
||||
public boolean hasModel() {
|
||||
return this != NONE;
|
||||
}
|
||||
}
|
||||
|
||||
public FluidPipeAttachmentBehaviour(SmartTileEntity te) {
|
||||
super(te);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BehaviourType<?> getType() {
|
||||
return TYPE;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,524 @@
|
|||
package com.simibubi.create.content.contraptions.fluids;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.simibubi.create.AllSpecialTextures;
|
||||
import com.simibubi.create.CreateClient;
|
||||
import com.simibubi.create.content.contraptions.KineticDebugger;
|
||||
import com.simibubi.create.foundation.fluid.FluidHelper;
|
||||
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
|
||||
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||
import com.simibubi.create.foundation.tileEntity.behaviour.BehaviourType;
|
||||
import com.simibubi.create.foundation.utility.Couple;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
import com.simibubi.create.foundation.utility.LerpedFloat;
|
||||
import com.simibubi.create.foundation.utility.LerpedFloat.Chaser;
|
||||
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||
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.entity.Entity;
|
||||
import net.minecraft.fluid.Fluid;
|
||||
import net.minecraft.fluid.Fluids;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.nbt.ListNBT;
|
||||
import net.minecraft.particles.BlockParticleData;
|
||||
import net.minecraft.particles.IParticleData;
|
||||
import net.minecraft.particles.ParticleTypes;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.common.util.Constants.NBT;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
import net.minecraftforge.fml.DistExecutor;
|
||||
|
||||
public abstract class FluidPipeBehaviour extends TileEntityBehaviour {
|
||||
|
||||
public static BehaviourType<FluidPipeBehaviour> TYPE = new BehaviourType<>();
|
||||
|
||||
// Direction -> (inboundflows{}, outwardflows{})
|
||||
Map<Direction, Couple<PipeFlows>> allFlows;
|
||||
FluidStack fluid;
|
||||
Couple<FluidStack> collision;
|
||||
|
||||
public FluidPipeBehaviour(SmartTileEntity te) {
|
||||
super(te);
|
||||
allFlows = new IdentityHashMap<>();
|
||||
fluid = FluidStack.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BehaviourType<?> getType() {
|
||||
return TYPE;
|
||||
}
|
||||
|
||||
public void notifyNetwork() {
|
||||
FluidPropagator.propagateChangedPipe(this.getWorld(), tileEntity.getPos(), tileEntity.getBlockState());
|
||||
}
|
||||
|
||||
public boolean canTransferToward(FluidStack fluid, BlockState state, Direction direction, boolean inbound) {
|
||||
return isConnectedTo(state, direction);
|
||||
}
|
||||
|
||||
public abstract boolean isConnectedTo(BlockState state, Direction direction);
|
||||
|
||||
public float getRimRadius(BlockState state, Direction direction) {
|
||||
return 1 / 4f + 1 / 64f;
|
||||
}
|
||||
|
||||
public boolean hasStartedFlow(FluidNetworkFlow flow, Direction face, boolean inbound) {
|
||||
return allFlows.containsKey(face) && allFlows.get(face)
|
||||
.get(inbound)
|
||||
.hasFlow(flow);
|
||||
}
|
||||
|
||||
public boolean hasCompletedFlow(Direction face, boolean inbound) {
|
||||
return allFlows.containsKey(face) && allFlows.get(face)
|
||||
.get(inbound)
|
||||
.isCompleted();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(CompoundNBT compound, boolean client) {
|
||||
compound.put("Fluid", fluid.writeToNBT(new CompoundNBT()));
|
||||
ListNBT flows = new ListNBT();
|
||||
for (Direction face : Iterate.directions)
|
||||
for (boolean inbound : Iterate.trueAndFalse) {
|
||||
LerpedFloat flowProgress = getFlowProgress(face, inbound);
|
||||
if (flowProgress == null)
|
||||
continue;
|
||||
CompoundNBT nbt = new CompoundNBT();
|
||||
NBTHelper.writeEnum(nbt, "Face", face);
|
||||
nbt.putBoolean("In", inbound);
|
||||
PipeFlows pipeFlows = allFlows.get(face)
|
||||
.get(inbound);
|
||||
Set<FluidNetworkFlow> participants = pipeFlows.participants;
|
||||
nbt.putBoolean("Silent", participants == null || participants.isEmpty());
|
||||
nbt.put("Progress", flowProgress.writeNBT());
|
||||
|
||||
if (client)
|
||||
nbt.putFloat("Strength", pipeFlows.bestFlowStrength);
|
||||
|
||||
flows.add(nbt);
|
||||
}
|
||||
compound.put("Flows", flows);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(CompoundNBT compound, boolean client) {
|
||||
fluid = FluidStack.loadFluidStackFromNBT(compound.getCompound("Fluid"));
|
||||
|
||||
if (client) {
|
||||
for (Direction face : Iterate.directions)
|
||||
if (allFlows.containsKey(face))
|
||||
allFlows.get(face)
|
||||
.forEach(pf -> pf.progress = null);
|
||||
}
|
||||
|
||||
NBTHelper.iterateCompoundList(compound.getList("Flows", NBT.TAG_COMPOUND), nbt -> {
|
||||
Direction face = NBTHelper.readEnum(nbt, "Face", Direction.class);
|
||||
boolean inbound = nbt.getBoolean("In");
|
||||
LerpedFloat progress = createFlowProgress(0);
|
||||
progress.readNBT(nbt.getCompound("Progress"), false);
|
||||
addFlow(null, face, inbound, nbt.getBoolean("Silent"));
|
||||
setFlowProgress(face, inbound, progress);
|
||||
if (client)
|
||||
setVisualFlowStrength(face, inbound, nbt.getFloat("Strength"));
|
||||
});
|
||||
|
||||
if (!client)
|
||||
return;
|
||||
|
||||
for (Direction face : Iterate.directions) {
|
||||
if (!allFlows.containsKey(face))
|
||||
return;
|
||||
Couple<PipeFlows> couple = allFlows.get(face);
|
||||
if (couple.get(true).progress == null && couple.get(false).progress == null)
|
||||
allFlows.remove(face);
|
||||
if (allFlows.isEmpty())
|
||||
clear();
|
||||
}
|
||||
}
|
||||
|
||||
public void addFlow(@Nullable FluidNetworkFlow flow, Direction face, boolean inbound, boolean silent) {
|
||||
if (flow != null) {
|
||||
FluidStack fluid = flow.getFluidStack();
|
||||
if (!this.fluid.isEmpty() && !fluid.isFluidEqual(this.fluid)) {
|
||||
collision = Couple.create(this.fluid, fluid);
|
||||
return;
|
||||
}
|
||||
this.fluid = fluid;
|
||||
}
|
||||
|
||||
if (!allFlows.containsKey(face)) {
|
||||
allFlows.put(face, Couple.create(PipeFlows::new));
|
||||
if (inbound && !silent)
|
||||
spawnSplashOnRim(face);
|
||||
}
|
||||
|
||||
if (flow != null) {
|
||||
PipeFlows flows = allFlows.get(face)
|
||||
.get(inbound);
|
||||
flows.addFlow(flow);
|
||||
contentsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public void removeFlow(FluidNetworkFlow flow, Direction face, boolean inbound) {
|
||||
if (!allFlows.containsKey(face))
|
||||
return;
|
||||
Couple<PipeFlows> couple = allFlows.get(face);
|
||||
couple.get(inbound)
|
||||
.removeFlow(flow);
|
||||
contentsChanged();
|
||||
if (!couple.get(true)
|
||||
.isActive()
|
||||
&& !couple.get(false)
|
||||
.isActive())
|
||||
allFlows.remove(face);
|
||||
if (allFlows.isEmpty())
|
||||
clear();
|
||||
}
|
||||
|
||||
public void setVisualFlowStrength(Direction face, boolean inbound, float strength) {
|
||||
if (!allFlows.containsKey(face))
|
||||
return;
|
||||
allFlows.get(face)
|
||||
.get(inbound).bestFlowStrength = strength;
|
||||
}
|
||||
|
||||
public void setFlowProgress(Direction face, boolean inbound, LerpedFloat progress) {
|
||||
if (!allFlows.containsKey(face))
|
||||
return;
|
||||
allFlows.get(face)
|
||||
.get(inbound).progress = progress;
|
||||
}
|
||||
|
||||
public LerpedFloat getFlowProgress(Direction face, boolean inbound) {
|
||||
if (!allFlows.containsKey(face))
|
||||
return null;
|
||||
return allFlows.get(face)
|
||||
.get(inbound).progress;
|
||||
}
|
||||
|
||||
public void skipFlow(Direction face, boolean inbound) {
|
||||
if (!allFlows.containsKey(face))
|
||||
return;
|
||||
Couple<PipeFlows> couple = allFlows.get(face);
|
||||
couple.get(inbound)
|
||||
.skip();
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
allFlows.clear();
|
||||
fluid = FluidStack.EMPTY;
|
||||
contentsChanged();
|
||||
}
|
||||
|
||||
public void spawnParticles() {
|
||||
DistExecutor.runWhenOn(Dist.CLIENT, () -> this::spawnParticlesInner);
|
||||
}
|
||||
|
||||
public void spawnSplashOnRim(Direction face) {
|
||||
DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> spawnSplashOnRimInner(face));
|
||||
}
|
||||
|
||||
public static final int MAX_PARTICLE_RENDER_DISTANCE = 20;
|
||||
public static final int SPLASH_PARTICLE_AMOUNT = 1;
|
||||
public static final float IDLE_PARTICLE_SPAWN_CHANCE = 1 / 800f;
|
||||
public static final Random r = new Random();
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
private void spawnParticlesInner() {
|
||||
if (!isRenderEntityWithinDistance())
|
||||
return;
|
||||
if (fluid.isEmpty())
|
||||
return;
|
||||
|
||||
World world = Minecraft.getInstance().world;
|
||||
BlockPos pos = tileEntity.getPos();
|
||||
BlockState state = world.getBlockState(pos);
|
||||
|
||||
for (Direction face : Iterate.directions) {
|
||||
boolean open = FluidPropagator.isOpenEnd(world, pos, face);
|
||||
if (isConnectedTo(state, face)) {
|
||||
if (open) {
|
||||
spawnPouringLiquid(world, state, fluid, face, 1);
|
||||
continue;
|
||||
}
|
||||
if (r.nextFloat() < IDLE_PARTICLE_SPAWN_CHANCE)
|
||||
spawnRimParticles(world, state, fluid, face, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
private void spawnSplashOnRimInner(Direction face) {
|
||||
if (!isRenderEntityWithinDistance())
|
||||
return;
|
||||
if (fluid.isEmpty())
|
||||
return;
|
||||
World world = Minecraft.getInstance().world;
|
||||
BlockPos pos = tileEntity.getPos();
|
||||
BlockState state = world.getBlockState(pos);
|
||||
spawnRimParticles(world, state, fluid, face, SPLASH_PARTICLE_AMOUNT);
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
private void spawnRimParticles(World world, BlockState state, FluidStack fluid, Direction side, int amount) {
|
||||
BlockPos pos = tileEntity.getPos();
|
||||
if (FluidPropagator.isOpenEnd(world, pos, side)) {
|
||||
spawnPouringLiquid(world, state, fluid, side, amount);
|
||||
return;
|
||||
}
|
||||
|
||||
IParticleData particle = null;
|
||||
if (FluidHelper.isWater(fluid.getFluid()))
|
||||
particle = ParticleTypes.DRIPPING_WATER;
|
||||
if (FluidHelper.isLava(fluid.getFluid()))
|
||||
particle = ParticleTypes.DRIPPING_LAVA;
|
||||
// TODO: Generic drip particle type for forge fluids
|
||||
|
||||
if (particle == null)
|
||||
return;
|
||||
|
||||
float rimRadius = getRimRadius(state, side);
|
||||
Vec3d directionVec = new Vec3d(side.getDirectionVec());
|
||||
|
||||
for (int i = 0; i < amount; i++) {
|
||||
Vec3d vec = VecHelper.offsetRandomly(Vec3d.ZERO, r, 1)
|
||||
.normalize();
|
||||
vec = VecHelper.clampComponentWise(vec, rimRadius)
|
||||
.mul(VecHelper.axisAlingedPlaneOf(directionVec))
|
||||
.add(directionVec.scale(.45 + r.nextFloat() / 16f));
|
||||
Vec3d m = vec;
|
||||
vec = vec.add(VecHelper.getCenterOf(pos));
|
||||
|
||||
world.addOptionalParticle(particle, vec.x, vec.y - 1 / 16f, vec.z, m.x, m.y, m.z);
|
||||
}
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
private void spawnPouringLiquid(World world, BlockState state, FluidStack fluid, Direction side, int amount) {
|
||||
IParticleData particle = new BlockParticleData(ParticleTypes.BLOCK, fluid.getFluid()
|
||||
.getDefaultState()
|
||||
.getBlockState());
|
||||
float rimRadius = getRimRadius(state, side);
|
||||
Vec3d directionVec = new Vec3d(side.getDirectionVec());
|
||||
|
||||
Couple<PipeFlows> couple = allFlows.get(side);
|
||||
if (couple == null)
|
||||
return;
|
||||
couple.forEachWithContext((flow, inbound) -> {
|
||||
if (flow.progress == null)
|
||||
return;
|
||||
for (int i = 0; i < amount; i++) {
|
||||
Vec3d vec = VecHelper.offsetRandomly(Vec3d.ZERO, r, rimRadius);
|
||||
vec = vec.mul(VecHelper.axisAlingedPlaneOf(directionVec))
|
||||
.add(directionVec.scale(.5 + r.nextFloat() / 4f));
|
||||
Vec3d m = vec;
|
||||
Vec3d centerOf = VecHelper.getCenterOf(tileEntity.getPos());
|
||||
vec = vec.add(centerOf);
|
||||
if (inbound) {
|
||||
vec = vec.add(m);
|
||||
m = centerOf.add(directionVec.scale(.5))
|
||||
.subtract(vec)
|
||||
.scale(3);
|
||||
}
|
||||
world.addOptionalParticle(particle, vec.x, vec.y - 1 / 16f, vec.z, m.x, m.y, m.z);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
private boolean isRenderEntityWithinDistance() {
|
||||
Entity renderViewEntity = Minecraft.getInstance()
|
||||
.getRenderViewEntity();
|
||||
if (renderViewEntity == null)
|
||||
return false;
|
||||
Vec3d center = VecHelper.getCenterOf(tileEntity.getPos());
|
||||
if (renderViewEntity.getPositionVec()
|
||||
.distanceTo(center) > MAX_PARTICLE_RENDER_DISTANCE)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static AxisAlignedBB smallCenter = new AxisAlignedBB(BlockPos.ZERO).shrink(.25);
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
boolean isRemote = getWorld().isRemote;
|
||||
|
||||
allFlows.values()
|
||||
.forEach(c -> c.forEach(pf -> pf.tick(isRemote)));
|
||||
|
||||
if (isRemote) {
|
||||
clientTick();
|
||||
return;
|
||||
}
|
||||
|
||||
if (collision != null) {
|
||||
FluidReactions.handlePipeFlowCollision(getWorld(), tileEntity.getPos(), collision.getFirst(),
|
||||
collision.getSecond());
|
||||
collision = null;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public Pair<Boolean, LerpedFloat> getStrogestFlow(Direction side) {
|
||||
Couple<PipeFlows> couple = allFlows.get(side);
|
||||
if (couple == null)
|
||||
return null;
|
||||
|
||||
PipeFlows in = couple.get(true);
|
||||
PipeFlows out = couple.get(false);
|
||||
Couple<LerpedFloat> progress = couple.map(pf -> pf.progress);
|
||||
boolean inboundStronger = false;
|
||||
|
||||
if (in.isCompleted() != out.isCompleted()) {
|
||||
inboundStronger = in.isCompleted();
|
||||
} else if ((progress.get(true) == null) != (progress.get(false) == null)) {
|
||||
inboundStronger = progress.get(true) != null;
|
||||
} else {
|
||||
if (progress.get(true) != null)
|
||||
inboundStronger = in.bestFlowStrength > out.bestFlowStrength;
|
||||
}
|
||||
|
||||
return Pair.of(inboundStronger, progress.get(inboundStronger));
|
||||
}
|
||||
|
||||
private void clientTick() {
|
||||
spawnParticles();
|
||||
|
||||
if (!KineticDebugger.isActive())
|
||||
return;
|
||||
if (fluid.isEmpty())
|
||||
return;
|
||||
for (Entry<Direction, Couple<PipeFlows>> entry : allFlows.entrySet()) {
|
||||
Direction face = entry.getKey();
|
||||
Vec3d directionVec = new Vec3d(face.getDirectionVec());
|
||||
float size = 1 / 4f;
|
||||
boolean extended = !isConnectedTo(tileEntity.getBlockState(), face.getOpposite());
|
||||
float length = extended ? .75f : .5f;
|
||||
|
||||
entry.getValue()
|
||||
.forEachWithContext((flow, inbound) -> {
|
||||
if (flow.progress == null)
|
||||
return;
|
||||
float value = flow.progress.getValue();
|
||||
Vec3d start = directionVec.scale(inbound ? .5 : .5f - length);
|
||||
Vec3d offset = directionVec.scale(length * (inbound ? -1 : 1))
|
||||
.scale(value);
|
||||
|
||||
Vec3d scale = new Vec3d(1, 1, 1).subtract(directionVec.scale(face.getAxisDirection()
|
||||
.getOffset()))
|
||||
.scale(size);
|
||||
AxisAlignedBB bb =
|
||||
new AxisAlignedBB(start, start.add(offset)).offset(VecHelper.getCenterOf(tileEntity.getPos()))
|
||||
.grow(scale.x, scale.y, scale.z);
|
||||
|
||||
int color = 0x7fdbda;
|
||||
if (!fluid.isEmpty()) {
|
||||
Fluid fluid2 = fluid.getFluid();
|
||||
if (fluid2 == Fluids.WATER)
|
||||
color = 0x1D4D9B;
|
||||
if (fluid2 == Fluids.LAVA)
|
||||
color = 0xFF773D;
|
||||
}
|
||||
|
||||
CreateClient.outliner.chaseAABB(Pair.of(this, face), bb)
|
||||
.withFaceTexture(AllSpecialTextures.CUTOUT_CHECKERED)
|
||||
.colored(color)
|
||||
.lineWidth(1 / 16f);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void contentsChanged() {
|
||||
tileEntity.markDirty();
|
||||
tileEntity.sendData();
|
||||
}
|
||||
|
||||
private LerpedFloat createFlowProgress(double speed) {
|
||||
return LerpedFloat.linear()
|
||||
.startWithValue(0)
|
||||
.chase(1, speed, Chaser.LINEAR);
|
||||
}
|
||||
|
||||
public FluidStack getFluid() {
|
||||
return fluid;
|
||||
}
|
||||
|
||||
class PipeFlows {
|
||||
LerpedFloat progress;
|
||||
Set<FluidNetworkFlow> participants;
|
||||
float bestFlowStrength;
|
||||
|
||||
void addFlow(FluidNetworkFlow flow) {
|
||||
if (participants == null)
|
||||
participants = new HashSet<>();
|
||||
participants.add(flow);
|
||||
|
||||
if (progress == null) {
|
||||
progress = createFlowProgress(flow.getSpeed());
|
||||
}
|
||||
}
|
||||
|
||||
boolean hasFlow(FluidNetworkFlow flow) {
|
||||
return participants != null && participants.contains(flow);
|
||||
}
|
||||
|
||||
void tick(boolean onClient) {
|
||||
if (progress == null)
|
||||
return;
|
||||
if (!onClient) {
|
||||
if (participants == null)
|
||||
return;
|
||||
bestFlowStrength = 0;
|
||||
for (FluidNetworkFlow networkFlow : participants)
|
||||
bestFlowStrength = Math.max(bestFlowStrength, networkFlow.getSpeed());
|
||||
if (isCompleted())
|
||||
return;
|
||||
if (progress.updateChaseSpeed(bestFlowStrength))
|
||||
contentsChanged();
|
||||
}
|
||||
progress.tickChaser();
|
||||
}
|
||||
|
||||
void skip() {
|
||||
progress = LerpedFloat.linear()
|
||||
.startWithValue(1);
|
||||
}
|
||||
|
||||
void removeFlow(FluidNetworkFlow flow) {
|
||||
if (participants == null)
|
||||
return;
|
||||
participants.remove(flow);
|
||||
}
|
||||
|
||||
boolean isActive() {
|
||||
return participants != null && !participants.isEmpty();
|
||||
}
|
||||
|
||||
boolean isCompleted() {
|
||||
return progress != null && progress.getValue() == 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,157 +0,0 @@
|
|||
package com.simibubi.create.content.contraptions.fluids;
|
||||
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.IWaterLoggable;
|
||||
import net.minecraft.block.SixWayBlock;
|
||||
import net.minecraft.fluid.Fluids;
|
||||
import net.minecraft.fluid.IFluidState;
|
||||
import net.minecraft.item.BlockItemUseContext;
|
||||
import net.minecraft.state.StateContainer.Builder;
|
||||
import net.minecraft.state.properties.BlockStateProperties;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.Direction.Axis;
|
||||
import net.minecraft.util.Direction.AxisDirection;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IBlockReader;
|
||||
import net.minecraft.world.ILightReader;
|
||||
import net.minecraft.world.IWorld;
|
||||
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class FluidPipeBlock extends SixWayBlock implements IWaterLoggable {
|
||||
|
||||
public FluidPipeBlock(Properties properties) {
|
||||
super(4 / 16f, properties);
|
||||
this.setDefaultState(super.getDefaultState().with(BlockStateProperties.WATERLOGGED, false));
|
||||
}
|
||||
|
||||
public static boolean isPipe(BlockState state) {
|
||||
return state.getBlock() instanceof FluidPipeBlock;
|
||||
}
|
||||
|
||||
public static boolean isTank(BlockState state, IBlockReader world, BlockPos pos, Direction blockFace) {
|
||||
return state.hasTileEntity() && world.getTileEntity(pos).getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, blockFace.getOpposite()).isPresent();
|
||||
}
|
||||
|
||||
// TODO: more generic pipe connection handling. Ideally without marker interface
|
||||
public static boolean canConnectTo(ILightReader world, BlockPos pos, BlockState neighbour, Direction blockFace) {
|
||||
if (isPipe(neighbour) || isTank(neighbour, world, pos, blockFace))
|
||||
return true;
|
||||
return neighbour.getBlock() instanceof PumpBlock && blockFace.getAxis() == neighbour.get(PumpBlock.FACING)
|
||||
.getAxis();
|
||||
}
|
||||
|
||||
public static boolean shouldDrawRim(ILightReader world, BlockPos pos, BlockState state, Direction direction) {
|
||||
if (!isPipe(state))
|
||||
return false;
|
||||
if (!state.get(FACING_TO_PROPERTY_MAP.get(direction)))
|
||||
return false;
|
||||
BlockPos offsetPos = pos.offset(direction);
|
||||
BlockState facingState = world.getBlockState(offsetPos);
|
||||
if (facingState.getBlock() instanceof PumpBlock && facingState.get(PumpBlock.FACING)
|
||||
.getAxis() == direction.getAxis())
|
||||
return false;
|
||||
if (!isPipe(facingState))
|
||||
return true;
|
||||
if (!isCornerOrEndPipe(world, pos, state))
|
||||
return false;
|
||||
if (isStraightPipe(world, offsetPos, facingState))
|
||||
return true;
|
||||
if (!shouldDrawCasing(world, pos, state) && shouldDrawCasing(world, offsetPos, facingState))
|
||||
return true;
|
||||
if (isCornerOrEndPipe(world, offsetPos, facingState))
|
||||
return direction.getAxisDirection() == AxisDirection.POSITIVE;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isCornerOrEndPipe(ILightReader world, BlockPos pos, BlockState state) {
|
||||
return isPipe(state) && !isStraightPipe(world, pos, state) && !shouldDrawCasing(world, pos, state);
|
||||
}
|
||||
|
||||
public static boolean isStraightPipe(ILightReader world, BlockPos pos, BlockState state) {
|
||||
if (!isPipe(state))
|
||||
return false;
|
||||
boolean axisFound = false;
|
||||
for (Axis axis : Iterate.axes) {
|
||||
Direction d1 = Direction.getFacingFromAxis(AxisDirection.NEGATIVE, axis);
|
||||
Direction d2 = Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis);
|
||||
if (state.get(FACING_TO_PROPERTY_MAP.get(d1)) && state.get(FACING_TO_PROPERTY_MAP.get(d2)))
|
||||
if (axisFound)
|
||||
return false;
|
||||
else
|
||||
axisFound = true;
|
||||
}
|
||||
return axisFound;
|
||||
}
|
||||
|
||||
public static boolean shouldDrawCasing(ILightReader world, BlockPos pos, BlockState state) {
|
||||
if (!isPipe(state))
|
||||
return false;
|
||||
for (Axis axis : Iterate.axes) {
|
||||
int connections = 0;
|
||||
for (Direction direction : Iterate.directions)
|
||||
if (direction.getAxis() != axis && state.get(FACING_TO_PROPERTY_MAP.get(direction)))
|
||||
connections++;
|
||||
if (connections > 2)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fillStateContainer(Builder<Block, BlockState> builder) {
|
||||
builder.add(NORTH, EAST, SOUTH, WEST, UP, DOWN, BlockStateProperties.WATERLOGGED);
|
||||
super.fillStateContainer(builder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getStateForPlacement(BlockItemUseContext context) {
|
||||
IFluidState ifluidstate = context.getWorld().getFluidState(context.getPos());
|
||||
return updateBlockState(getDefaultState(), context.getNearestLookingDirection(), null, context.getWorld(),
|
||||
context.getPos()).with(BlockStateProperties.WATERLOGGED, Boolean.valueOf(ifluidstate.getFluid() == Fluids.WATER));
|
||||
}
|
||||
|
||||
@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 updateBlockState(state, direction, direction.getOpposite(), world, pos);
|
||||
}
|
||||
|
||||
public BlockState updateBlockState(BlockState state, Direction preferredDirection, @Nullable Direction ignore,
|
||||
ILightReader world, BlockPos pos) {
|
||||
// Update sides that are not ignored
|
||||
for (Direction d : Iterate.directions)
|
||||
if (d != ignore)
|
||||
state = state.with(FACING_TO_PROPERTY_MAP.get(d),
|
||||
canConnectTo(world, pos.offset(d), world.getBlockState(pos.offset(d)), d.getOpposite()));
|
||||
|
||||
// See if it has enough connections
|
||||
Direction connectedDirection = null;
|
||||
for (Direction d : Iterate.directions) {
|
||||
if (state.get(FACING_TO_PROPERTY_MAP.get(d))) {
|
||||
if (connectedDirection != null)
|
||||
return state;
|
||||
connectedDirection = d;
|
||||
}
|
||||
}
|
||||
|
||||
// Add opposite end if only one connection
|
||||
if (connectedDirection != null)
|
||||
return state.with(FACING_TO_PROPERTY_MAP.get(connectedDirection.getOpposite()), true);
|
||||
|
||||
// Use preferred
|
||||
return state.with(FACING_TO_PROPERTY_MAP.get(preferredDirection), true)
|
||||
.with(FACING_TO_PROPERTY_MAP.get(preferredDirection.getOpposite()), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IFluidState getFluidState(BlockState state) {
|
||||
return state.get(BlockStateProperties.WATERLOGGED) ? Fluids.WATER.getStillFluidState(false) : Fluids.EMPTY.getDefaultState();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,189 @@
|
|||
package com.simibubi.create.content.contraptions.fluids;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang3.mutable.MutableObject;
|
||||
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.CreateClient;
|
||||
import com.simibubi.create.content.contraptions.fluids.pipes.AxisPipeBlock;
|
||||
import com.simibubi.create.content.contraptions.fluids.pipes.FluidPipeBlock;
|
||||
import com.simibubi.create.foundation.config.AllConfigs;
|
||||
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||
import com.simibubi.create.foundation.utility.BlockFace;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
import com.simibubi.create.foundation.utility.outliner.Outline.OutlineParams;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.FlowingFluidBlock;
|
||||
import net.minecraft.state.properties.BlockStateProperties;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.Direction.Axis;
|
||||
import net.minecraft.util.Direction.AxisDirection;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.IBlockReader;
|
||||
import net.minecraft.world.IWorld;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
|
||||
import net.minecraftforge.fml.DistExecutor;
|
||||
|
||||
public class FluidPropagator {
|
||||
|
||||
public static Direction validateNeighbourChange(BlockState state, World world, BlockPos pos, Block otherBlock,
|
||||
BlockPos neighborPos, boolean isMoving) {
|
||||
if (world.isRemote)
|
||||
return null;
|
||||
if (otherBlock instanceof FluidPipeBlock)
|
||||
return null;
|
||||
if (otherBlock instanceof AxisPipeBlock)
|
||||
return null;
|
||||
if (otherBlock instanceof PumpBlock)
|
||||
return null;
|
||||
if (otherBlock instanceof FlowingFluidBlock)
|
||||
return null;
|
||||
if (!isStraightPipe(state))
|
||||
return null;
|
||||
for (Direction d : Iterate.directions) {
|
||||
if (!pos.offset(d)
|
||||
.equals(neighborPos))
|
||||
continue;
|
||||
return d;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static FluidPipeBehaviour getPipe(IBlockReader reader, BlockPos pos) {
|
||||
return TileEntityBehaviour.get(reader, pos, FluidPipeBehaviour.TYPE);
|
||||
}
|
||||
|
||||
public static boolean isOpenEnd(IBlockReader reader, BlockPos pos, Direction side) {
|
||||
BlockPos connectedPos = pos.offset(side);
|
||||
BlockState connectedState = reader.getBlockState(connectedPos);
|
||||
FluidPipeBehaviour pipe = FluidPropagator.getPipe(reader, connectedPos);
|
||||
if (pipe != null && pipe.isConnectedTo(connectedState, side.getOpposite()))
|
||||
return false;
|
||||
if (PumpBlock.isPump(connectedState) && connectedState.get(PumpBlock.FACING)
|
||||
.getAxis() == side.getAxis())
|
||||
return false;
|
||||
if (Block.hasSolidSide(connectedState, reader, connectedPos, side.getOpposite()))
|
||||
return false;
|
||||
if (!(connectedState.getMaterial()
|
||||
.isReplaceable() && connectedState.getBlockHardness(reader, connectedPos) != -1)
|
||||
&& !connectedState.has(BlockStateProperties.WATERLOGGED))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void propagateChangedPipe(IWorld world, BlockPos pipePos, BlockState pipeState) {
|
||||
List<BlockPos> frontier = new ArrayList<>();
|
||||
Set<BlockPos> visited = new HashSet<>();
|
||||
|
||||
frontier.add(pipePos);
|
||||
|
||||
// Visit all connected pumps to update their network
|
||||
while (!frontier.isEmpty()) {
|
||||
BlockPos currentPos = frontier.remove(0);
|
||||
if (visited.contains(currentPos))
|
||||
continue;
|
||||
visited.add(currentPos);
|
||||
BlockState currentState = currentPos.equals(pipePos) ? pipeState : world.getBlockState(currentPos);
|
||||
FluidPipeBehaviour pipe = getPipe(world, currentPos);
|
||||
if (pipe == null)
|
||||
continue;
|
||||
for (Direction direction : getPipeConnections(currentState, pipe)) {
|
||||
BlockPos target = currentPos.offset(direction);
|
||||
if (!world.isAreaLoaded(target, 0))
|
||||
continue;
|
||||
|
||||
TileEntity tileEntity = world.getTileEntity(target);
|
||||
BlockState targetState = world.getBlockState(target);
|
||||
if (tileEntity instanceof PumpTileEntity) {
|
||||
if (!AllBlocks.MECHANICAL_PUMP.has(targetState) || targetState.get(PumpBlock.FACING)
|
||||
.getAxis() != direction.getAxis())
|
||||
continue;
|
||||
PumpTileEntity pump = (PumpTileEntity) tileEntity;
|
||||
pump.updatePipesOnSide(direction.getOpposite());
|
||||
continue;
|
||||
}
|
||||
if (visited.contains(target))
|
||||
continue;
|
||||
FluidPipeBehaviour targetPipe = getPipe(world, target);
|
||||
if (targetPipe == null)
|
||||
continue;
|
||||
if (targetPipe.isConnectedTo(targetState, direction.getOpposite()))
|
||||
frontier.add(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static List<Direction> getPipeConnections(BlockState state, FluidPipeBehaviour pipe) {
|
||||
List<Direction> list = new ArrayList<>();
|
||||
for (Direction d : Iterate.directions)
|
||||
if (pipe.isConnectedTo(state, d))
|
||||
list.add(d);
|
||||
return list;
|
||||
}
|
||||
|
||||
public static int getPumpRange() {
|
||||
return AllConfigs.SERVER.fluids.mechanicalPumpRange.get();
|
||||
}
|
||||
|
||||
public static OutlineParams showBlockFace(BlockFace face) {
|
||||
MutableObject<OutlineParams> params = new MutableObject<>(new OutlineParams());
|
||||
DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> {
|
||||
Vec3d directionVec = new Vec3d(face.getFace()
|
||||
.getDirectionVec());
|
||||
Vec3d scaleVec = directionVec.scale(-.25f * face.getFace()
|
||||
.getAxisDirection()
|
||||
.getOffset());
|
||||
directionVec = directionVec.scale(.5f);
|
||||
params.setValue(CreateClient.outliner.showAABB(face,
|
||||
FluidPropagator.smallCenter.offset(directionVec.add(new Vec3d(face.getPos())))
|
||||
.grow(scaleVec.x, scaleVec.y, scaleVec.z)
|
||||
.grow(1 / 16f)));
|
||||
});
|
||||
return params.getValue();
|
||||
}
|
||||
|
||||
static AxisAlignedBB smallCenter = new AxisAlignedBB(BlockPos.ZERO).shrink(.25);
|
||||
|
||||
public static boolean hasFluidCapability(BlockState state, IBlockReader world, BlockPos pos, Direction blockFace) {
|
||||
return state.hasTileEntity() && world.getTileEntity(pos)
|
||||
.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, blockFace.getOpposite())
|
||||
.isPresent();
|
||||
}
|
||||
|
||||
public static boolean isStraightPipe(BlockState state) {
|
||||
if (state.getBlock() instanceof AxisPipeBlock)
|
||||
return true;
|
||||
if (!FluidPipeBlock.isPipe(state))
|
||||
return false;
|
||||
boolean axisFound = false;
|
||||
int connections = 0;
|
||||
for (Axis axis : Iterate.axes) {
|
||||
Direction d1 = Direction.getFacingFromAxis(AxisDirection.NEGATIVE, axis);
|
||||
Direction d2 = Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis);
|
||||
boolean openAt1 = FluidPipeBlock.isOpenAt(state, d1);
|
||||
boolean openAt2 = FluidPipeBlock.isOpenAt(state, d2);
|
||||
if (openAt1)
|
||||
connections++;
|
||||
if (openAt2)
|
||||
connections++;
|
||||
if (openAt1 && openAt2)
|
||||
if (axisFound)
|
||||
return false;
|
||||
else
|
||||
axisFound = true;
|
||||
}
|
||||
return axisFound && connections == 2;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package com.simibubi.create.content.contraptions.fluids;
|
||||
|
||||
import com.simibubi.create.foundation.fluid.FluidHelper;
|
||||
import com.simibubi.create.foundation.utility.BlockHelper;
|
||||
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.fluid.Fluid;
|
||||
import net.minecraft.fluid.Fluids;
|
||||
import net.minecraft.fluid.IFluidState;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
|
||||
public class FluidReactions {
|
||||
|
||||
public static void handlePipeFlowCollision(World world, BlockPos pos, FluidStack fluid, FluidStack fluid2) {
|
||||
Fluid f1 = fluid.getFluid();
|
||||
Fluid f2 = fluid2.getFluid();
|
||||
BlockHelper.destroyBlock(world, pos, 1);
|
||||
if (f1 == Fluids.WATER && f2 == Fluids.LAVA || f2 == Fluids.WATER && f1 == Fluids.LAVA)
|
||||
world.setBlockState(pos, Blocks.COBBLESTONE.getDefaultState());
|
||||
}
|
||||
|
||||
public static void handlePipeSpillCollision(World world, BlockPos pos, Fluid pipeFluid, IFluidState worldFluid) {
|
||||
Fluid pf = FluidHelper.convertToStill(pipeFluid);
|
||||
Fluid wf = worldFluid.getFluid();
|
||||
if (pf == Fluids.WATER && wf == Fluids.LAVA)
|
||||
world.setBlockState(pos, Blocks.OBSIDIAN.getDefaultState());
|
||||
if (pf == Fluids.WATER && wf == Fluids.FLOWING_LAVA)
|
||||
world.setBlockState(pos, Blocks.COBBLESTONE.getDefaultState());
|
||||
else if (pf == Fluids.LAVA && wf == Fluids.WATER)
|
||||
world.setBlockState(pos, Blocks.STONE.getDefaultState());
|
||||
else if (pf == Fluids.LAVA && wf == Fluids.FLOWING_WATER)
|
||||
world.setBlockState(pos, Blocks.COBBLESTONE.getDefaultState());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package com.simibubi.create.content.contraptions.fluids;
|
||||
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
import net.minecraftforge.fluids.capability.templates.FluidTank;
|
||||
|
||||
public class InterPumpFluidHandler extends FluidTank {
|
||||
|
||||
InterPumpEndpoint endpoint;
|
||||
|
||||
public InterPumpFluidHandler(InterPumpEndpoint endpoint) {
|
||||
super(Integer.MAX_VALUE);
|
||||
this.endpoint = endpoint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int fill(FluidStack resource, FluidAction action) {
|
||||
if (resource.isEmpty())
|
||||
return 0;
|
||||
int maxInput = Math.min(resource.getAmount(), Math.max(getTransferCapacity() - getFluidAmount(), 0));
|
||||
FluidStack toInsert = resource.copy();
|
||||
toInsert.setAmount(maxInput);
|
||||
FluidPropagator.showBlockFace(endpoint.location).colored(0x77d196).lineWidth(1/4f);
|
||||
return super.fill(toInsert, action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FluidStack drain(int maxDrain, FluidAction action) {
|
||||
return super.drain(maxDrain, action);
|
||||
}
|
||||
|
||||
public FluidStack provide() {
|
||||
FluidStack heldFluid = getFluid();
|
||||
if (heldFluid.isEmpty())
|
||||
return heldFluid;
|
||||
FluidStack copy = heldFluid.copy();
|
||||
copy.setAmount(1);
|
||||
return copy;
|
||||
}
|
||||
|
||||
private int getTransferCapacity() {
|
||||
return Math.min(endpoint.getTransferSpeed(true), endpoint.getTransferSpeed(false));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,172 @@
|
|||
package com.simibubi.create.content.contraptions.fluids;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.simibubi.create.foundation.utility.BlockFace;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.FlowingFluidBlock;
|
||||
import net.minecraft.fluid.Fluid;
|
||||
import net.minecraft.fluid.Fluids;
|
||||
import net.minecraft.fluid.IFluidState;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.state.properties.BlockStateProperties;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
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 OpenEndedPipe {
|
||||
|
||||
World world;
|
||||
|
||||
private OpenEndFluidHandler fluidHandler;
|
||||
private BlockPos outputPos;
|
||||
private boolean wasPulling;
|
||||
private boolean stale;
|
||||
|
||||
public OpenEndedPipe(BlockFace face) {
|
||||
fluidHandler = new OpenEndFluidHandler();
|
||||
outputPos = face.getConnectedPos();
|
||||
}
|
||||
|
||||
public void tick(World world, boolean pulling) {
|
||||
this.world = world;
|
||||
if (!world.isAreaLoaded(outputPos, 0))
|
||||
return;
|
||||
if (pulling != wasPulling) {
|
||||
if (pulling)
|
||||
fluidHandler.clear();
|
||||
wasPulling = pulling;
|
||||
}
|
||||
|
||||
BlockState state = world.getBlockState(outputPos);
|
||||
IFluidState fluidState = state.getFluidState();
|
||||
boolean waterlog = state.has(BlockStateProperties.WATERLOGGED);
|
||||
|
||||
if (!waterlog && !state.getMaterial()
|
||||
.isReplaceable())
|
||||
return;
|
||||
|
||||
// TODO different pipe end types
|
||||
if (pulling) {
|
||||
if (fluidState.isEmpty() || !fluidState.isSource())
|
||||
return;
|
||||
if (!fluidHandler.tryCollectFluid(fluidState.getFluid()))
|
||||
return;
|
||||
if (waterlog) {
|
||||
world.setBlockState(outputPos, state.with(BlockStateProperties.WATERLOGGED, false), 3);
|
||||
return;
|
||||
}
|
||||
world.setBlockState(outputPos, fluidState.getBlockState()
|
||||
.with(FlowingFluidBlock.LEVEL, 14), 3);
|
||||
return;
|
||||
}
|
||||
|
||||
Fluid providedFluid = fluidHandler.tryProvidingFluid();
|
||||
if (providedFluid == null)
|
||||
return;
|
||||
if (!fluidState.isEmpty() && fluidState.getFluid() != providedFluid) {
|
||||
FluidReactions.handlePipeSpillCollision(world, outputPos, providedFluid, fluidState);
|
||||
return;
|
||||
}
|
||||
if (fluidState.isSource())
|
||||
return;
|
||||
if (waterlog) {
|
||||
if (providedFluid.getFluid() != Fluids.WATER)
|
||||
return;
|
||||
world.setBlockState(outputPos, state.with(BlockStateProperties.WATERLOGGED, true), 3);
|
||||
return;
|
||||
}
|
||||
world.setBlockState(outputPos, providedFluid.getDefaultState()
|
||||
.getBlockState(), 3);
|
||||
}
|
||||
|
||||
public LazyOptional<IFluidHandler> getCapability() {
|
||||
return LazyOptional.of(() -> fluidHandler);
|
||||
}
|
||||
|
||||
public CompoundNBT writeToNBT(CompoundNBT compound) {
|
||||
fluidHandler.writeToNBT(compound);
|
||||
compound.putBoolean("Pulling", wasPulling);
|
||||
return compound;
|
||||
}
|
||||
|
||||
public void readNBT(CompoundNBT compound) {
|
||||
fluidHandler.readFromNBT(compound);
|
||||
wasPulling = compound.getBoolean("Pulling");
|
||||
}
|
||||
|
||||
public void markStale() {
|
||||
stale = true;
|
||||
}
|
||||
|
||||
public void unmarkStale() {
|
||||
stale = false;
|
||||
}
|
||||
|
||||
public boolean isStale() {
|
||||
return stale;
|
||||
}
|
||||
|
||||
private class OpenEndFluidHandler extends FluidTank {
|
||||
|
||||
public OpenEndFluidHandler() {
|
||||
super(1500);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int fill(FluidStack resource, FluidAction action) {
|
||||
// Never allow being filled when a source is attached
|
||||
if (world == null)
|
||||
return 0;
|
||||
if (!world.isAreaLoaded(outputPos, 0))
|
||||
return 0;
|
||||
if (resource.isEmpty())
|
||||
return 0;
|
||||
BlockState state = world.getBlockState(outputPos);
|
||||
IFluidState fluidState = state.getFluidState();
|
||||
if (!fluidState.isEmpty() && fluidState.getFluid() != resource.getFluid()) {
|
||||
FluidReactions.handlePipeSpillCollision(world, outputPos, resource.getFluid(), fluidState);
|
||||
return 0;
|
||||
}
|
||||
if (fluidState.isSource())
|
||||
return 0;
|
||||
if (!(state.has(BlockStateProperties.WATERLOGGED) && resource.getFluid() == Fluids.WATER)
|
||||
&& !state.getMaterial()
|
||||
.isReplaceable())
|
||||
return 0;
|
||||
|
||||
// Never allow being filled above 1000
|
||||
FluidStack insertable = resource.copy();
|
||||
insertable.setAmount(Math.min(insertable.getAmount(), Math.max(1000 - getFluidAmount(), 0)));
|
||||
return super.fill(insertable, action);
|
||||
}
|
||||
|
||||
public boolean tryCollectFluid(Fluid fluid) {
|
||||
for (boolean simulate : Iterate.trueAndFalse)
|
||||
if (super.fill(new FluidStack(fluid, 1000),
|
||||
simulate ? FluidAction.SIMULATE : FluidAction.EXECUTE) != 1000)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Fluid tryProvidingFluid() {
|
||||
Fluid fluid = getFluid().getFluid();
|
||||
for (boolean simulate : Iterate.trueAndFalse)
|
||||
if (drain(1000, simulate ? FluidAction.SIMULATE : FluidAction.EXECUTE).getAmount() != 1000)
|
||||
return null;
|
||||
return fluid;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
setFluid(FluidStack.EMPTY);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,11 +1,15 @@
|
|||
package com.simibubi.create.content.contraptions.fluids;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import com.simibubi.create.AllBlockPartials;
|
||||
import com.simibubi.create.content.contraptions.fluids.FluidPipeAttachmentBehaviour.AttachmentTypes;
|
||||
import com.simibubi.create.content.contraptions.fluids.pipes.FluidPipeBlock;
|
||||
import com.simibubi.create.foundation.block.render.WrappedBakedModel;
|
||||
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
|
@ -18,19 +22,22 @@ import net.minecraftforge.client.model.data.IModelData;
|
|||
import net.minecraftforge.client.model.data.ModelDataMap;
|
||||
import net.minecraftforge.client.model.data.ModelProperty;
|
||||
|
||||
public class FluidPipeModel extends WrappedBakedModel {
|
||||
public class PipeAttachmentModel extends WrappedBakedModel {
|
||||
|
||||
private static ModelProperty<PipeModelData> PIPE_PROPERTY = new ModelProperty<>();
|
||||
|
||||
public FluidPipeModel(IBakedModel template) {
|
||||
public PipeAttachmentModel(IBakedModel template) {
|
||||
super(template);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IModelData getModelData(ILightReader world, BlockPos pos, BlockState state, IModelData tileData) {
|
||||
PipeModelData data = new PipeModelData();
|
||||
for (Direction d : Iterate.directions)
|
||||
data.putRim(d, FluidPipeBlock.shouldDrawRim(world, pos, state, d));
|
||||
FluidPipeAttachmentBehaviour attachmentBehaviour =
|
||||
TileEntityBehaviour.get(world, pos, FluidPipeAttachmentBehaviour.TYPE);
|
||||
if (attachmentBehaviour != null)
|
||||
for (Direction d : Iterate.directions)
|
||||
data.putRim(d, attachmentBehaviour.getAttachment(world, pos, state, d));
|
||||
data.setEncased(FluidPipeBlock.shouldDrawCasing(world, pos, state));
|
||||
return new ModelDataMap.Builder().withInitial(PIPE_PROPERTY, data)
|
||||
.build();
|
||||
|
@ -41,8 +48,10 @@ public class FluidPipeModel extends WrappedBakedModel {
|
|||
List<BakedQuad> quads = super.getQuads(state, side, rand, data);
|
||||
if (data instanceof ModelDataMap) {
|
||||
ModelDataMap modelDataMap = (ModelDataMap) data;
|
||||
if (modelDataMap.hasProperty(PIPE_PROPERTY))
|
||||
if (modelDataMap.hasProperty(PIPE_PROPERTY)) {
|
||||
quads = new ArrayList<>(quads);
|
||||
addQuads(quads, state, side, rand, modelDataMap, modelDataMap.getData(PIPE_PROPERTY));
|
||||
}
|
||||
}
|
||||
return quads;
|
||||
}
|
||||
|
@ -50,8 +59,9 @@ public class FluidPipeModel extends WrappedBakedModel {
|
|||
private void addQuads(List<BakedQuad> quads, BlockState state, Direction side, Random rand, IModelData data,
|
||||
PipeModelData pipeData) {
|
||||
for (Direction d : Iterate.directions)
|
||||
if (pipeData.getRim(d))
|
||||
quads.addAll(AllBlockPartials.PIPE_RIMS.get(d)
|
||||
if (pipeData.hasRim(d))
|
||||
quads.addAll(AllBlockPartials.PIPE_ATTACHMENTS.get(pipeData.getRim(d))
|
||||
.get(d)
|
||||
.get()
|
||||
.getQuads(state, side, rand, data));
|
||||
if (pipeData.isEncased())
|
||||
|
@ -60,15 +70,15 @@ public class FluidPipeModel extends WrappedBakedModel {
|
|||
}
|
||||
|
||||
private class PipeModelData {
|
||||
boolean[] rims;
|
||||
AttachmentTypes[] rims;
|
||||
boolean encased;
|
||||
|
||||
public PipeModelData() {
|
||||
rims = new boolean[6];
|
||||
Arrays.fill(rims, false);
|
||||
rims = new AttachmentTypes[6];
|
||||
Arrays.fill(rims, AttachmentTypes.NONE);
|
||||
}
|
||||
|
||||
public void putRim(Direction face, boolean rim) {
|
||||
public void putRim(Direction face, AttachmentTypes rim) {
|
||||
rims[face.getIndex()] = rim;
|
||||
}
|
||||
|
||||
|
@ -76,7 +86,11 @@ public class FluidPipeModel extends WrappedBakedModel {
|
|||
this.encased = encased;
|
||||
}
|
||||
|
||||
public boolean getRim(Direction face) {
|
||||
public boolean hasRim(Direction face) {
|
||||
return rims[face.getIndex()] != AttachmentTypes.NONE;
|
||||
}
|
||||
|
||||
public AttachmentTypes getRim(Direction face) {
|
||||
return rims[face.getIndex()];
|
||||
}
|
||||
|
|
@ -1,14 +1,24 @@
|
|||
package com.simibubi.create.content.contraptions.fluids;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.mutable.MutableBoolean;
|
||||
|
||||
import com.simibubi.create.AllShapes;
|
||||
import com.simibubi.create.AllTileEntities;
|
||||
import com.simibubi.create.content.contraptions.base.DirectionalKineticBlock;
|
||||
import com.simibubi.create.content.contraptions.fluids.pipes.FluidPipeBlock;
|
||||
import com.simibubi.create.foundation.utility.BlockFace;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.IWaterLoggable;
|
||||
import net.minecraft.fluid.Fluids;
|
||||
import net.minecraft.fluid.IFluidState;
|
||||
import net.minecraft.item.BlockItemUseContext;
|
||||
import net.minecraft.item.ItemUseContext;
|
||||
import net.minecraft.network.DebugPacketSender;
|
||||
import net.minecraft.state.StateContainer.Builder;
|
||||
import net.minecraft.state.properties.BlockStateProperties;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
|
@ -20,71 +30,137 @@ import net.minecraft.util.math.shapes.VoxelShape;
|
|||
import net.minecraft.world.IBlockReader;
|
||||
import net.minecraft.world.IWorld;
|
||||
import net.minecraft.world.IWorldReader;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
|
||||
public class PumpBlock extends DirectionalKineticBlock implements IWaterLoggable {
|
||||
|
||||
public PumpBlock(Properties p_i48415_1_) {
|
||||
super(p_i48415_1_);
|
||||
setDefaultState(super.getDefaultState().with(BlockStateProperties.WATERLOGGED, false));
|
||||
}
|
||||
public PumpBlock(Properties p_i48415_1_) {
|
||||
super(p_i48415_1_);
|
||||
setDefaultState(super.getDefaultState().with(BlockStateProperties.WATERLOGGED, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasTileEntity(BlockState state) {
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public boolean hasTileEntity(BlockState state) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TileEntity createTileEntity(BlockState state, IBlockReader world) {
|
||||
return AllTileEntities.MECHANICAL_PUMP.create();
|
||||
}
|
||||
@Override
|
||||
public TileEntity createTileEntity(BlockState state, IBlockReader world) {
|
||||
return AllTileEntities.MECHANICAL_PUMP.create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getRotatedBlockState(BlockState originalState, Direction targetedFace) {
|
||||
return originalState.with(FACING, originalState.get(FACING)
|
||||
.getOpposite());
|
||||
}
|
||||
@Override
|
||||
public BlockState getRotatedBlockState(BlockState originalState, Direction targetedFace) {
|
||||
return originalState.with(FACING, originalState.get(FACING)
|
||||
.getOpposite());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Axis getRotationAxis(BlockState state) {
|
||||
return state.get(FACING)
|
||||
.getAxis();
|
||||
}
|
||||
@Override
|
||||
public BlockState updateAfterWrenched(BlockState newState, ItemUseContext context) {
|
||||
BlockState state = super.updateAfterWrenched(newState, context);
|
||||
World world = context.getWorld();
|
||||
BlockPos pos = context.getPos();
|
||||
if (world.isRemote)
|
||||
return state;
|
||||
TileEntity tileEntity = world.getTileEntity(pos);
|
||||
if (!(tileEntity instanceof PumpTileEntity))
|
||||
return state;
|
||||
PumpTileEntity pump = (PumpTileEntity) tileEntity;
|
||||
if (pump.networks == null)
|
||||
return state;
|
||||
|
||||
@Override
|
||||
public VoxelShape getShape(BlockState state, IBlockReader p_220053_2_, BlockPos p_220053_3_,
|
||||
ISelectionContext p_220053_4_) {
|
||||
return AllShapes.PUMP.get(state.get(FACING));
|
||||
}
|
||||
FluidNetwork apn1 = pump.networks.get(true);
|
||||
FluidNetwork apn2 = pump.networks.get(false);
|
||||
|
||||
@Override
|
||||
public boolean hasIntegratedCogwheel(IWorldReader world, BlockPos pos, BlockState state) {
|
||||
return true;
|
||||
}
|
||||
// Collect pipes that can be skipped
|
||||
apn1.clearFlows(world, true);
|
||||
apn2.clearFlows(world, true);
|
||||
|
||||
@Override
|
||||
public IFluidState getFluidState(BlockState state) {
|
||||
return state.get(BlockStateProperties.WATERLOGGED) ? Fluids.WATER.getStillFluidState(false) : Fluids.EMPTY.getDefaultState();
|
||||
}
|
||||
// Swap skipsets as the networks change sides
|
||||
Map<BlockFace, FluidStack> skippedConnections = apn1.previousFlow;
|
||||
apn1.previousFlow = apn2.previousFlow;
|
||||
apn2.previousFlow = skippedConnections;
|
||||
|
||||
@Override
|
||||
protected void fillStateContainer(Builder<Block, BlockState> builder) {
|
||||
builder.add(BlockStateProperties.WATERLOGGED);
|
||||
super.fillStateContainer(builder);
|
||||
}
|
||||
// Init networks next tick
|
||||
pump.networksToUpdate.forEach(MutableBoolean::setTrue);
|
||||
pump.networks.swap();
|
||||
pump.reversed = !pump.reversed;
|
||||
|
||||
@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;
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getStateForPlacement(BlockItemUseContext context) {
|
||||
IFluidState ifluidstate = context.getWorld().getFluidState(context.getPos());
|
||||
return super.getStateForPlacement(context).with(BlockStateProperties.WATERLOGGED, Boolean.valueOf(ifluidstate.getFluid() == Fluids.WATER));
|
||||
}
|
||||
@Override
|
||||
public Axis getRotationAxis(BlockState state) {
|
||||
return state.get(FACING)
|
||||
.getAxis();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoxelShape getShape(BlockState state, IBlockReader p_220053_2_, BlockPos p_220053_3_,
|
||||
ISelectionContext p_220053_4_) {
|
||||
return AllShapes.PUMP.get(state.get(FACING));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasIntegratedCogwheel(IWorldReader world, BlockPos pos, BlockState state) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void neighborChanged(BlockState state, World world, BlockPos pos, Block otherBlock, BlockPos neighborPos,
|
||||
boolean isMoving) {
|
||||
DebugPacketSender.func_218806_a(world, pos);
|
||||
if (world.isRemote)
|
||||
return;
|
||||
if (otherBlock instanceof FluidPipeBlock)
|
||||
return;
|
||||
TileEntity tileEntity = world.getTileEntity(pos);
|
||||
if (!(tileEntity instanceof PumpTileEntity))
|
||||
return;
|
||||
PumpTileEntity pump = (PumpTileEntity) tileEntity;
|
||||
Direction facing = state.get(FACING);
|
||||
for (boolean front : Iterate.trueAndFalse) {
|
||||
Direction side = front ? facing : facing.getOpposite();
|
||||
if (!pos.offset(side)
|
||||
.equals(neighborPos))
|
||||
continue;
|
||||
pump.updatePipesOnSide(side);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IFluidState 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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getStateForPlacement(BlockItemUseContext context) {
|
||||
IFluidState ifluidstate = context.getWorld()
|
||||
.getFluidState(context.getPos());
|
||||
return super.getStateForPlacement(context).with(BlockStateProperties.WATERLOGGED,
|
||||
Boolean.valueOf(ifluidstate.getFluid() == Fluids.WATER));
|
||||
}
|
||||
|
||||
public static boolean isPump(BlockState state) {
|
||||
return state.getBlock() instanceof PumpBlock;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ public class PumpRenderer extends KineticTileEntityRenderer {
|
|||
PumpTileEntity pump = (PumpTileEntity) te;
|
||||
Vec3d rotationOffset = new Vec3d(.5, 14 / 16f, .5);
|
||||
BlockState blockState = te.getBlockState();
|
||||
float angle = MathHelper.lerp(pump.arrowDirection.get(partialTicks), 0, 90) - 90;
|
||||
float angle = MathHelper.lerp(pump.arrowDirection.getValue(partialTicks), 0, 90) - 90;
|
||||
for (float yRot : new float[] { 0, 90 }) {
|
||||
ms.push();
|
||||
SuperByteBuffer arrow = AllBlockPartials.MECHANICAL_PUMP_ARROW.renderOn(blockState);
|
||||
|
|
|
@ -1,29 +1,380 @@
|
|||
package com.simibubi.create.content.contraptions.fluids;
|
||||
|
||||
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
||||
import com.simibubi.create.foundation.gui.widgets.InterpolatedChasingValue;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.mutable.MutableBoolean;
|
||||
|
||||
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
||||
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
|
||||
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||
import com.simibubi.create.foundation.utility.BlockFace;
|
||||
import com.simibubi.create.foundation.utility.Couple;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
import com.simibubi.create.foundation.utility.LerpedFloat;
|
||||
import com.simibubi.create.foundation.utility.LerpedFloat.Chaser;
|
||||
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.nbt.ListNBT;
|
||||
import net.minecraft.tileentity.TileEntityType;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.ILightReader;
|
||||
import net.minecraftforge.common.util.Constants.NBT;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
import net.minecraftforge.fluids.capability.IFluidHandler;
|
||||
import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction;
|
||||
|
||||
public class PumpTileEntity extends KineticTileEntity {
|
||||
|
||||
InterpolatedChasingValue arrowDirection;
|
||||
LerpedFloat arrowDirection;
|
||||
Couple<FluidNetwork> networks;
|
||||
Couple<Map<BlockFace, OpenEndedPipe>> openEnds;
|
||||
Couple<MutableBoolean> networksToUpdate;
|
||||
|
||||
boolean reversed;
|
||||
FluidStack providedFluid;
|
||||
|
||||
public PumpTileEntity(TileEntityType<?> typeIn) {
|
||||
super(typeIn);
|
||||
arrowDirection = new InterpolatedChasingValue();
|
||||
arrowDirection.start(1);
|
||||
arrowDirection = LerpedFloat.linear()
|
||||
.startWithValue(1);
|
||||
networksToUpdate = Couple.create(MutableBoolean::new);
|
||||
openEnds = Couple.create(HashMap::new);
|
||||
setProvidedFluid(FluidStack.EMPTY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
|
||||
super.addBehaviours(behaviours);
|
||||
behaviours.add(new PumpAttachmentBehaviour(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
super.initialize();
|
||||
reversed = getSpeed() < 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
float speed = getSpeed();
|
||||
|
||||
if (world.isRemote) {
|
||||
float speed = getSpeed();
|
||||
if (speed != 0)
|
||||
arrowDirection.target(Math.signum(speed));
|
||||
arrowDirection.tick();
|
||||
if (speed == 0)
|
||||
return;
|
||||
arrowDirection.chase(speed >= 0 ? 1 : -1, .5f, Chaser.EXP);
|
||||
arrowDirection.tickChaser();
|
||||
return;
|
||||
}
|
||||
|
||||
BlockState blockState = getBlockState();
|
||||
if (!(blockState.getBlock() instanceof PumpBlock))
|
||||
return;
|
||||
Direction face = blockState.get(PumpBlock.FACING);
|
||||
MutableBoolean networkUpdated = new MutableBoolean(false);
|
||||
|
||||
if (networks == null) {
|
||||
networks = Couple.create(new FluidNetwork(), new FluidNetwork());
|
||||
networks.forEachWithContext((fn, front) -> {
|
||||
BlockFace blockFace = new BlockFace(pos, front ? face : face.getOpposite());
|
||||
fn.assemble(world, this, blockFace);
|
||||
FluidPropagator.showBlockFace(blockFace)
|
||||
.lineWidth(1 / 8f);
|
||||
});
|
||||
networkUpdated.setTrue();
|
||||
}
|
||||
|
||||
networksToUpdate.forEachWithContext((update, front) -> {
|
||||
if (update.isFalse())
|
||||
return;
|
||||
FluidNetwork activePipeNetwork = networks.get(front);
|
||||
if (activePipeNetwork == null)
|
||||
return;
|
||||
BlockFace blockFace = new BlockFace(pos, front ? face : face.getOpposite());
|
||||
activePipeNetwork.reAssemble(world, this, blockFace);
|
||||
FluidPropagator.showBlockFace(blockFace)
|
||||
.lineWidth(1 / 8f);
|
||||
update.setFalse();
|
||||
networkUpdated.setTrue();
|
||||
});
|
||||
|
||||
if (networkUpdated.isTrue())
|
||||
return;
|
||||
|
||||
networks.forEach(fn -> fn.tick(world, this));
|
||||
|
||||
if (speed == 0)
|
||||
return;
|
||||
if (speed < 0 != reversed) {
|
||||
networks.forEachWithContext((fn, current) -> fn.clearFlows(world, true));
|
||||
reversed = speed < 0;
|
||||
return;
|
||||
}
|
||||
|
||||
boolean pullingSide = isPullingOnSide(true);
|
||||
float flowSpeed = Math.abs(speed) / 256f;
|
||||
|
||||
networks.forEachWithContext((fn, front) -> {
|
||||
boolean pulling = isPullingOnSide(front);
|
||||
fn.tickFlows(world, this, pulling, flowSpeed);
|
||||
openEnds.get(front)
|
||||
.values()
|
||||
.forEach(oep -> oep.tick(world, pulling));
|
||||
});
|
||||
|
||||
if (!networks.get(pullingSide)
|
||||
.hasEndpoints()) {
|
||||
setProvidedFluid(FluidStack.EMPTY);
|
||||
return;
|
||||
}
|
||||
|
||||
if (networks.getFirst()
|
||||
.hasEndpoints()
|
||||
&& networks.getSecond()
|
||||
.hasEndpoints()) {
|
||||
performTransfer();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
super.remove();
|
||||
if (networks != null)
|
||||
networks.forEachWithContext((fn, current) -> fn.clearFlows(world, false));
|
||||
}
|
||||
|
||||
private void performTransfer() {
|
||||
boolean input = isPullingOnSide(true);
|
||||
Collection<FluidNetworkEndpoint> inputs = networks.get(input)
|
||||
.getEndpoints(true);
|
||||
Collection<FluidNetworkEndpoint> outputs = networks.get(!input)
|
||||
.getEndpoints(false);
|
||||
|
||||
int flowSpeed = getFluidTransferSpeed();
|
||||
FluidStack transfer = FluidStack.EMPTY;
|
||||
for (boolean simulate : Iterate.trueAndFalse) {
|
||||
FluidAction action = simulate ? FluidAction.SIMULATE : FluidAction.EXECUTE;
|
||||
|
||||
List<FluidNetworkEndpoint> availableInputs = new ArrayList<>(inputs);
|
||||
while (!availableInputs.isEmpty() && transfer.getAmount() < flowSpeed) {
|
||||
int diff = flowSpeed - transfer.getAmount();
|
||||
int dividedTransfer = diff / availableInputs.size();
|
||||
int remainder = diff % availableInputs.size();
|
||||
|
||||
for (Iterator<FluidNetworkEndpoint> iterator = availableInputs.iterator(); iterator.hasNext();) {
|
||||
int toTransfer = dividedTransfer;
|
||||
if (remainder > 0) {
|
||||
toTransfer++;
|
||||
remainder--;
|
||||
}
|
||||
|
||||
FluidNetworkEndpoint ne = iterator.next();
|
||||
IFluidHandler handler = ne.provideHandler()
|
||||
.orElse(null);
|
||||
if (handler == null) {
|
||||
iterator.remove();
|
||||
continue;
|
||||
}
|
||||
FluidStack drained = handler.drain(toTransfer, action);
|
||||
if (drained.isEmpty()) {
|
||||
iterator.remove();
|
||||
continue;
|
||||
}
|
||||
if (transfer.isFluidEqual(drained) || transfer.isEmpty()) {
|
||||
if (drained.getAmount() < toTransfer)
|
||||
iterator.remove();
|
||||
FluidStack copy = drained.copy();
|
||||
copy.setAmount(drained.getAmount() + transfer.getAmount());
|
||||
transfer = copy;
|
||||
continue;
|
||||
}
|
||||
iterator.remove();
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
List<FluidNetworkEndpoint> availableOutputs = new ArrayList<>(outputs);
|
||||
while (!availableOutputs.isEmpty() && transfer.getAmount() > 0) {
|
||||
int dividedTransfer = transfer.getAmount() / availableOutputs.size();
|
||||
int remainder = transfer.getAmount() % availableOutputs.size();
|
||||
|
||||
for (Iterator<FluidNetworkEndpoint> iterator = availableOutputs.iterator(); iterator.hasNext();) {
|
||||
FluidNetworkEndpoint ne = iterator.next();
|
||||
int toTransfer = dividedTransfer;
|
||||
if (remainder > 0) {
|
||||
toTransfer++;
|
||||
remainder--;
|
||||
}
|
||||
|
||||
if (transfer.isEmpty())
|
||||
break;
|
||||
IFluidHandler handler = ne.provideHandler()
|
||||
.orElse(null);
|
||||
if (handler == null) {
|
||||
iterator.remove();
|
||||
continue;
|
||||
}
|
||||
|
||||
FluidStack divided = transfer.copy();
|
||||
divided.setAmount(toTransfer);
|
||||
int fill = handler.fill(divided, action);
|
||||
transfer.setAmount(transfer.getAmount() - fill);
|
||||
if (fill < toTransfer)
|
||||
iterator.remove();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
flowSpeed -= transfer.getAmount();
|
||||
transfer = FluidStack.EMPTY;
|
||||
}
|
||||
}
|
||||
|
||||
public int getFluidTransferSpeed() {
|
||||
float rotationSpeed = Math.abs(getSpeed());
|
||||
int flowSpeed = (int) (rotationSpeed / 2f);
|
||||
if (rotationSpeed != 0 && flowSpeed == 0)
|
||||
flowSpeed = 1;
|
||||
return flowSpeed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(CompoundNBT compound, boolean clientPacket) {
|
||||
compound.putBoolean("Reversed", reversed);
|
||||
serializeOpenEnds(compound);
|
||||
super.write(compound, clientPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void read(CompoundNBT compound, boolean clientPacket) {
|
||||
reversed = compound.getBoolean("Reversed");
|
||||
deserializeOpenEnds(compound);
|
||||
super.read(compound, clientPacket);
|
||||
}
|
||||
|
||||
public void updatePipesOnSide(Direction side) {
|
||||
if (!isSideAccessible(side))
|
||||
return;
|
||||
updatePipeNetwork(isFront(side));
|
||||
}
|
||||
|
||||
protected boolean isFront(Direction side) {
|
||||
if (networks == null)
|
||||
return false;
|
||||
BlockState blockState = getBlockState();
|
||||
if (!(blockState.getBlock() instanceof PumpBlock))
|
||||
return false;
|
||||
Direction front = blockState.get(PumpBlock.FACING);
|
||||
boolean isFront = side == front;
|
||||
return isFront;
|
||||
}
|
||||
|
||||
protected void updatePipeNetwork(boolean front) {
|
||||
if (networks != null)
|
||||
networks.get(front)
|
||||
.clearFlows(world, true);
|
||||
networksToUpdate.get(front)
|
||||
.setTrue();
|
||||
if (getSpeed() == 0 || (isPullingOnSide(front)) && networks != null)
|
||||
setProvidedFluid(FluidStack.EMPTY);
|
||||
}
|
||||
|
||||
public boolean isSideAccessible(Direction side) {
|
||||
BlockState blockState = getBlockState();
|
||||
if (!(blockState.getBlock() instanceof PumpBlock))
|
||||
return false;
|
||||
return blockState.get(PumpBlock.FACING)
|
||||
.getAxis() == side.getAxis();
|
||||
}
|
||||
|
||||
public boolean isPullingOnSide(boolean front) {
|
||||
return front == reversed;
|
||||
}
|
||||
|
||||
public Map<BlockFace, OpenEndedPipe> getOpenEnds(Direction side) {
|
||||
return openEnds.get(isFront(side));
|
||||
}
|
||||
|
||||
private void serializeOpenEnds(CompoundNBT compound) {
|
||||
compound.put("OpenEnds", openEnds.serializeEach(m -> {
|
||||
CompoundNBT compoundNBT = new CompoundNBT();
|
||||
ListNBT entries = new ListNBT();
|
||||
m.entrySet()
|
||||
.forEach(e -> {
|
||||
CompoundNBT innerCompound = new CompoundNBT();
|
||||
innerCompound.put("Pos", e.getKey()
|
||||
.serializeNBT());
|
||||
e.getValue()
|
||||
.writeToNBT(innerCompound);
|
||||
entries.add(innerCompound);
|
||||
});
|
||||
compoundNBT.put("Entries", entries);
|
||||
return compoundNBT;
|
||||
}));
|
||||
}
|
||||
|
||||
private void deserializeOpenEnds(CompoundNBT compound) {
|
||||
openEnds = Couple.deserializeEach(compound.getList("OpenEnds", NBT.TAG_COMPOUND), c -> {
|
||||
Map<BlockFace, OpenEndedPipe> map = new HashMap<>();
|
||||
NBTHelper.iterateCompoundList(c.getList("Entries", NBT.TAG_COMPOUND), innerCompound -> {
|
||||
BlockFace key = BlockFace.fromNBT(innerCompound.getCompound("Pos"));
|
||||
OpenEndedPipe value = new OpenEndedPipe(key);
|
||||
value.readNBT(innerCompound);
|
||||
map.put(key, value);
|
||||
});
|
||||
return map;
|
||||
});
|
||||
|
||||
compound.put("OpenEnds", openEnds.serializeEach(m -> {
|
||||
CompoundNBT compoundNBT = new CompoundNBT();
|
||||
ListNBT entries = new ListNBT();
|
||||
m.entrySet()
|
||||
.forEach(e -> {
|
||||
CompoundNBT innerCompound = new CompoundNBT();
|
||||
innerCompound.put("Pos", e.getKey()
|
||||
.serializeNBT());
|
||||
e.getValue()
|
||||
.writeToNBT(innerCompound);
|
||||
entries.add(innerCompound);
|
||||
});
|
||||
compoundNBT.put("Entries", entries);
|
||||
return compoundNBT;
|
||||
}));
|
||||
}
|
||||
|
||||
public void setProvidedFluid(FluidStack providedFluid) {
|
||||
this.providedFluid = providedFluid;
|
||||
}
|
||||
|
||||
class PumpAttachmentBehaviour extends FluidPipeAttachmentBehaviour {
|
||||
|
||||
public PumpAttachmentBehaviour(SmartTileEntity te) {
|
||||
super(te);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPipeConnectedTowards(BlockState state, Direction direction) {
|
||||
return isSideAccessible(direction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttachmentTypes getAttachment(ILightReader world, BlockPos pos, BlockState state, Direction direction) {
|
||||
AttachmentTypes attachment = super.getAttachment(world, pos, state, direction);
|
||||
if (attachment == AttachmentTypes.RIM)
|
||||
return AttachmentTypes.NONE;
|
||||
return attachment;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
package com.simibubi.create.content.contraptions.fluids.pipes;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.AllShapes;
|
||||
import com.simibubi.create.content.contraptions.fluids.FluidPropagator;
|
||||
import com.simibubi.create.content.contraptions.wrench.IWrenchable;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.RotatedPillarBlock;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.DebugPacketSender;
|
||||
import net.minecraft.state.BooleanProperty;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.Direction.AxisDirection;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.util.math.shapes.ISelectionContext;
|
||||
import net.minecraft.util.math.shapes.VoxelShape;
|
||||
import net.minecraft.world.IBlockReader;
|
||||
import net.minecraft.world.IWorld;
|
||||
import net.minecraft.world.TickPriority;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.server.ServerWorld;
|
||||
|
||||
public class AxisPipeBlock extends RotatedPillarBlock implements IWrenchable {
|
||||
|
||||
public AxisPipeBlock(Properties p_i48339_1_) {
|
||||
super(p_i48339_1_);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||
boolean blockTypeChanged = state.getBlock() != newState.getBlock();
|
||||
if (blockTypeChanged && !world.isRemote)
|
||||
FluidPropagator.propagateChangedPipe(world, pos, state);
|
||||
if (state.hasTileEntity() && (blockTypeChanged || !newState.hasTileEntity()))
|
||||
world.removeTileEntity(pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlockAdded(BlockState state, World world, BlockPos pos, BlockState oldState, boolean isMoving) {
|
||||
if (world.isRemote)
|
||||
return;
|
||||
if (state != oldState)
|
||||
world.getPendingBlockTicks()
|
||||
.scheduleTick(pos, this, 1, TickPriority.HIGH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getPickBlock(BlockState state, RayTraceResult target, IBlockReader world, BlockPos pos,
|
||||
PlayerEntity player) {
|
||||
return AllBlocks.FLUID_PIPE.asStack();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void neighborChanged(BlockState state, World world, BlockPos pos, Block otherBlock, BlockPos neighborPos,
|
||||
boolean isMoving) {
|
||||
DebugPacketSender.func_218806_a(world, pos);
|
||||
Direction d = FluidPropagator.validateNeighbourChange(state, world, pos, otherBlock, neighborPos, isMoving);
|
||||
if (d == null)
|
||||
return;
|
||||
if (!isOpenAt(state, d))
|
||||
return;
|
||||
world.getPendingBlockTicks()
|
||||
.scheduleTick(pos, this, 1, TickPriority.HIGH);
|
||||
}
|
||||
|
||||
public static boolean isOpenAt(BlockState state, Direction d) {
|
||||
return d.getAxis() == state.get(AXIS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scheduledTick(BlockState state, ServerWorld world, BlockPos pos, Random r) {
|
||||
FluidPropagator.propagateChangedPipe(world, pos, state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoxelShape getShape(BlockState state, IBlockReader p_220053_2_, BlockPos p_220053_3_,
|
||||
ISelectionContext p_220053_4_) {
|
||||
return AllShapes.EIGHT_VOXEL_POLE.get(state.get(AXIS));
|
||||
}
|
||||
|
||||
public BlockState toRegularPipe(IWorld world, BlockPos pos, BlockState state) {
|
||||
Direction side = Direction.getFacingFromAxis(AxisDirection.POSITIVE, state.get(AXIS));
|
||||
Map<Direction, BooleanProperty> facingToPropertyMap = FluidPipeBlock.FACING_TO_PROPERTY_MAP;
|
||||
return AllBlocks.FLUID_PIPE.get()
|
||||
.updateBlockState(AllBlocks.FLUID_PIPE.getDefaultState()
|
||||
.with(facingToPropertyMap.get(side), true)
|
||||
.with(facingToPropertyMap.get(side.getOpposite()), true), side, null, world, pos);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package com.simibubi.create.content.contraptions.fluids.pipes;
|
||||
|
||||
import com.simibubi.create.AllTileEntities;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.item.ItemUseContext;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.ActionResultType;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.shapes.ISelectionContext;
|
||||
import net.minecraft.util.math.shapes.VoxelShape;
|
||||
import net.minecraft.util.math.shapes.VoxelShapes;
|
||||
import net.minecraft.world.IBlockReader;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class EncasedPipeBlock extends AxisPipeBlock {
|
||||
|
||||
public EncasedPipeBlock(Properties p_i48339_1_) {
|
||||
super(p_i48339_1_);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasTileEntity(BlockState state) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TileEntity createTileEntity(BlockState state, IBlockReader world) {
|
||||
return AllTileEntities.ENCASED_FLUID_PIPE.create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoxelShape getShape(BlockState state, IBlockReader p_220053_2_, BlockPos p_220053_3_,
|
||||
ISelectionContext p_220053_4_) {
|
||||
return VoxelShapes.fullCube();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionResultType onWrenched(BlockState state, ItemUseContext context) {
|
||||
World world = context.getWorld();
|
||||
BlockPos pos = context.getPos();
|
||||
world.setBlockState(pos, toRegularPipe(world, pos, state), 3);
|
||||
return ActionResultType.SUCCESS;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,248 @@
|
|||
package com.simibubi.create.content.contraptions.fluids.pipes;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.AllTileEntities;
|
||||
import com.simibubi.create.content.contraptions.fluids.FluidPipeAttachmentBehaviour;
|
||||
import com.simibubi.create.content.contraptions.fluids.FluidPropagator;
|
||||
import com.simibubi.create.content.contraptions.wrench.IWrenchable;
|
||||
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.IWaterLoggable;
|
||||
import net.minecraft.block.SixWayBlock;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.fluid.Fluids;
|
||||
import net.minecraft.fluid.IFluidState;
|
||||
import net.minecraft.item.BlockItemUseContext;
|
||||
import net.minecraft.item.ItemUseContext;
|
||||
import net.minecraft.network.DebugPacketSender;
|
||||
import net.minecraft.state.StateContainer.Builder;
|
||||
import net.minecraft.state.properties.BlockStateProperties;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.ActionResultType;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.Direction.Axis;
|
||||
import net.minecraft.util.Direction.AxisDirection;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.BlockRayTraceResult;
|
||||
import net.minecraft.world.IBlockReader;
|
||||
import net.minecraft.world.ILightReader;
|
||||
import net.minecraft.world.IWorld;
|
||||
import net.minecraft.world.TickPriority;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.server.ServerWorld;
|
||||
|
||||
public class FluidPipeBlock extends SixWayBlock implements IWaterLoggable, IWrenchable {
|
||||
|
||||
public FluidPipeBlock(Properties properties) {
|
||||
super(4 / 16f, properties);
|
||||
this.setDefaultState(super.getDefaultState().with(BlockStateProperties.WATERLOGGED, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionResultType onWrenched(BlockState state, ItemUseContext context) {
|
||||
World world = context.getWorld();
|
||||
BlockPos pos = context.getPos();
|
||||
Axis axis = getAxis(world, pos, state);
|
||||
if (axis == null)
|
||||
return ActionResultType.PASS;
|
||||
if (context.getFace()
|
||||
.getAxis() == axis)
|
||||
return ActionResultType.PASS;
|
||||
if (!world.isRemote)
|
||||
world.setBlockState(pos, AllBlocks.GLASS_FLUID_PIPE.getDefaultState()
|
||||
.with(GlassFluidPipeBlock.AXIS, axis));
|
||||
return ActionResultType.SUCCESS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionResultType onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand,
|
||||
BlockRayTraceResult hit) {
|
||||
if (!AllBlocks.COPPER_CASING.isIn(player.getHeldItem(hand)))
|
||||
return ActionResultType.PASS;
|
||||
Axis axis = getAxis(world, pos, state);
|
||||
if (axis == null)
|
||||
return ActionResultType.PASS;
|
||||
if (!world.isRemote)
|
||||
world.setBlockState(pos, AllBlocks.ENCASED_FLUID_PIPE.getDefaultState()
|
||||
.with(EncasedPipeBlock.AXIS, axis));
|
||||
return ActionResultType.SUCCESS;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Axis getAxis(IBlockReader world, BlockPos pos, BlockState state) {
|
||||
if (!FluidPropagator.isStraightPipe(state))
|
||||
return null;
|
||||
Axis axis = null;
|
||||
for (Direction d : Iterate.directions) {
|
||||
if (isOpenAt(state, d)) {
|
||||
axis = d.getAxis();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return axis;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasTileEntity(BlockState state) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TileEntity createTileEntity(BlockState state, IBlockReader world) {
|
||||
return AllTileEntities.FLUID_PIPE.create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||
boolean blockTypeChanged = state.getBlock() != newState.getBlock();
|
||||
if (blockTypeChanged && !world.isRemote)
|
||||
FluidPropagator.propagateChangedPipe(world, pos, state);
|
||||
if (state.hasTileEntity() && (blockTypeChanged || !newState.hasTileEntity()))
|
||||
world.removeTileEntity(pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlockAdded(BlockState state, World world, BlockPos pos, BlockState oldState, boolean isMoving) {
|
||||
if (world.isRemote)
|
||||
return;
|
||||
if (state != oldState)
|
||||
world.getPendingBlockTicks()
|
||||
.scheduleTick(pos, this, 1, TickPriority.HIGH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void neighborChanged(BlockState state, World world, BlockPos pos, Block otherBlock, BlockPos neighborPos,
|
||||
boolean isMoving) {
|
||||
DebugPacketSender.func_218806_a(world, pos);
|
||||
Direction d = FluidPropagator.validateNeighbourChange(state, world, pos, otherBlock, neighborPos, isMoving);
|
||||
if (d == null)
|
||||
return;
|
||||
if (!isOpenAt(state, d))
|
||||
return;
|
||||
world.getPendingBlockTicks()
|
||||
.scheduleTick(pos, this, 1, TickPriority.HIGH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scheduledTick(BlockState state, ServerWorld world, BlockPos pos, Random r) {
|
||||
FluidPropagator.propagateChangedPipe(world, pos, state);
|
||||
}
|
||||
|
||||
public static boolean isPipe(BlockState state) {
|
||||
return state.getBlock() instanceof FluidPipeBlock;
|
||||
}
|
||||
|
||||
public static boolean canConnectTo(ILightReader world, BlockPos pos, BlockState neighbour, Direction blockFace) {
|
||||
if (isPipe(neighbour) || FluidPropagator.hasFluidCapability(neighbour, world, pos, blockFace))
|
||||
return true;
|
||||
FluidPipeAttachmentBehaviour attachmentBehaviour =
|
||||
TileEntityBehaviour.get(world, pos, FluidPipeAttachmentBehaviour.TYPE);
|
||||
if (attachmentBehaviour == null)
|
||||
return false;
|
||||
return attachmentBehaviour.isPipeConnectedTowards(neighbour, blockFace.getOpposite());
|
||||
}
|
||||
|
||||
public static boolean shouldDrawRim(ILightReader world, BlockPos pos, BlockState state, Direction direction) {
|
||||
BlockPos offsetPos = pos.offset(direction);
|
||||
BlockState facingState = world.getBlockState(offsetPos);
|
||||
if (!isPipe(facingState))
|
||||
return true;
|
||||
if (!isCornerOrEndPipe(world, pos, state))
|
||||
return false;
|
||||
if (FluidPropagator.isStraightPipe(facingState))
|
||||
return true;
|
||||
if (!shouldDrawCasing(world, pos, state) && shouldDrawCasing(world, offsetPos, facingState))
|
||||
return true;
|
||||
if (isCornerOrEndPipe(world, offsetPos, facingState))
|
||||
return direction.getAxisDirection() == AxisDirection.POSITIVE;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean isOpenAt(BlockState state, Direction direction) {
|
||||
return state.get(FACING_TO_PROPERTY_MAP.get(direction));
|
||||
}
|
||||
|
||||
public static boolean isCornerOrEndPipe(ILightReader world, BlockPos pos, BlockState state) {
|
||||
return isPipe(state) && !FluidPropagator.isStraightPipe(state) && !shouldDrawCasing(world, pos, state);
|
||||
}
|
||||
|
||||
public static boolean shouldDrawCasing(ILightReader world, BlockPos pos, BlockState state) {
|
||||
if (!isPipe(state))
|
||||
return false;
|
||||
for (Axis axis : Iterate.axes) {
|
||||
int connections = 0;
|
||||
for (Direction direction : Iterate.directions)
|
||||
if (direction.getAxis() != axis && isOpenAt(state, direction))
|
||||
connections++;
|
||||
if (connections > 2)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fillStateContainer(Builder<Block, BlockState> builder) {
|
||||
builder.add(NORTH, EAST, SOUTH, WEST, UP, DOWN, BlockStateProperties.WATERLOGGED);
|
||||
super.fillStateContainer(builder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getStateForPlacement(BlockItemUseContext context) {
|
||||
IFluidState ifluidstate = context.getWorld()
|
||||
.getFluidState(context.getPos());
|
||||
return updateBlockState(getDefaultState(), context.getNearestLookingDirection(), null, context.getWorld(),
|
||||
context.getPos()).with(BlockStateProperties.WATERLOGGED,
|
||||
Boolean.valueOf(ifluidstate.getFluid() == Fluids.WATER));
|
||||
}
|
||||
|
||||
@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 updateBlockState(state, direction, direction.getOpposite(), world, pos);
|
||||
}
|
||||
|
||||
public BlockState updateBlockState(BlockState state, Direction preferredDirection, @Nullable Direction ignore,
|
||||
ILightReader world, BlockPos pos) {
|
||||
// Update sides that are not ignored
|
||||
for (Direction d : Iterate.directions)
|
||||
if (d != ignore)
|
||||
state = state.with(FACING_TO_PROPERTY_MAP.get(d),
|
||||
canConnectTo(world, pos.offset(d), world.getBlockState(pos.offset(d)), d.getOpposite()));
|
||||
|
||||
// See if it has enough connections
|
||||
Direction connectedDirection = null;
|
||||
for (Direction d : Iterate.directions) {
|
||||
if (isOpenAt(state, d)) {
|
||||
if (connectedDirection != null)
|
||||
return state;
|
||||
connectedDirection = d;
|
||||
}
|
||||
}
|
||||
|
||||
// Add opposite end if only one connection
|
||||
if (connectedDirection != null)
|
||||
return state.with(FACING_TO_PROPERTY_MAP.get(connectedDirection.getOpposite()), true);
|
||||
|
||||
// Use preferred
|
||||
return state.with(FACING_TO_PROPERTY_MAP.get(preferredDirection), true)
|
||||
.with(FACING_TO_PROPERTY_MAP.get(preferredDirection.getOpposite()), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IFluidState getFluidState(BlockState state) {
|
||||
return state.get(BlockStateProperties.WATERLOGGED) ? Fluids.WATER.getStillFluidState(false)
|
||||
: Fluids.EMPTY.getDefaultState();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package com.simibubi.create.content.contraptions.fluids.pipes;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.simibubi.create.content.contraptions.fluids.FluidPipeAttachmentBehaviour;
|
||||
import com.simibubi.create.content.contraptions.fluids.FluidPipeBehaviour;
|
||||
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
|
||||
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.tileentity.TileEntityType;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.ILightReader;
|
||||
|
||||
public class FluidPipeTileEntity extends SmartTileEntity {
|
||||
|
||||
public FluidPipeTileEntity(TileEntityType<?> tileEntityTypeIn) {
|
||||
super(tileEntityTypeIn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
|
||||
behaviours.add(new StandardPipeBehaviour(this));
|
||||
behaviours.add(new StandardPipeAttachmentBehaviour(this));
|
||||
}
|
||||
|
||||
class StandardPipeBehaviour extends FluidPipeBehaviour {
|
||||
|
||||
public StandardPipeBehaviour(SmartTileEntity te) {
|
||||
super(te);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConnectedTo(BlockState state, Direction direction) {
|
||||
return FluidPipeBlock.isPipe(state) && state.get(FluidPipeBlock.FACING_TO_PROPERTY_MAP.get(direction));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class StandardPipeAttachmentBehaviour extends FluidPipeAttachmentBehaviour {
|
||||
|
||||
public StandardPipeAttachmentBehaviour(SmartTileEntity te) {
|
||||
super(te);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttachmentTypes getAttachment(ILightReader world, BlockPos pos, BlockState state, Direction direction) {
|
||||
AttachmentTypes attachment = super.getAttachment(world, pos, state, direction);
|
||||
|
||||
BlockPos offsetPos = pos.offset(direction);
|
||||
if (!FluidPipeBlock.isPipe(world.getBlockState(offsetPos))) {
|
||||
FluidPipeAttachmentBehaviour attachmentBehaviour =
|
||||
TileEntityBehaviour.get(world, offsetPos, FluidPipeAttachmentBehaviour.TYPE);
|
||||
if (attachmentBehaviour != null && attachmentBehaviour
|
||||
.isPipeConnectedTowards(world.getBlockState(offsetPos), direction.getOpposite()))
|
||||
return AttachmentTypes.NONE;
|
||||
}
|
||||
|
||||
if (attachment == AttachmentTypes.RIM && !FluidPipeBlock.shouldDrawRim(world, pos, state, direction))
|
||||
return AttachmentTypes.NONE;
|
||||
return attachment;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package com.simibubi.create.content.contraptions.fluids.pipes;
|
||||
|
||||
import com.simibubi.create.AllTileEntities;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.item.ItemUseContext;
|
||||
import net.minecraft.state.BooleanProperty;
|
||||
import net.minecraft.state.StateContainer.Builder;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.ActionResultType;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IBlockReader;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class GlassFluidPipeBlock extends AxisPipeBlock {
|
||||
|
||||
public static final BooleanProperty ALT = BooleanProperty.create("alt");
|
||||
|
||||
public GlassFluidPipeBlock(Properties p_i48339_1_) {
|
||||
super(p_i48339_1_);
|
||||
setDefaultState(getDefaultState().with(ALT, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fillStateContainer(Builder<Block, BlockState> p_206840_1_) {
|
||||
super.fillStateContainer(p_206840_1_.add(ALT));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasTileEntity(BlockState state) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TileEntity createTileEntity(BlockState state, IBlockReader world) {
|
||||
return AllTileEntities.GLASS_FLUID_PIPE.create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionResultType onWrenched(BlockState state, ItemUseContext context) {
|
||||
BlockState newState = state;
|
||||
World world = context.getWorld();
|
||||
BlockPos pos = context.getPos();
|
||||
if (!state.get(ALT))
|
||||
newState = state.with(ALT, true);
|
||||
else
|
||||
newState = toRegularPipe(world, pos, state);
|
||||
world.setBlockState(pos, newState, 3);
|
||||
return ActionResultType.SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
package com.simibubi.create.content.contraptions.fluids.pipes;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.simibubi.create.content.contraptions.fluids.FluidPipeAttachmentBehaviour;
|
||||
import com.simibubi.create.content.contraptions.fluids.FluidPipeBehaviour;
|
||||
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
|
||||
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.tileentity.TileEntityType;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.Direction.AxisDirection;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.ILightReader;
|
||||
|
||||
public class StraightPipeTileEntity extends SmartTileEntity {
|
||||
|
||||
public StraightPipeTileEntity(TileEntityType<?> tileEntityTypeIn) {
|
||||
super(tileEntityTypeIn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
|
||||
behaviours.add(new StraightPipeBehaviour(this));
|
||||
behaviours.add(new StraightPipeAttachmentBehaviour(this));
|
||||
}
|
||||
|
||||
class StraightPipeBehaviour extends FluidPipeBehaviour {
|
||||
|
||||
public StraightPipeBehaviour(SmartTileEntity te) {
|
||||
super(te);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConnectedTo(BlockState state, Direction direction) {
|
||||
return state.get(AxisPipeBlock.AXIS) == direction.getAxis();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class StraightPipeAttachmentBehaviour extends FluidPipeAttachmentBehaviour {
|
||||
|
||||
public StraightPipeAttachmentBehaviour(SmartTileEntity te) {
|
||||
super(te);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttachmentTypes getAttachment(ILightReader world, BlockPos pos, BlockState state, Direction direction) {
|
||||
AttachmentTypes attachment = super.getAttachment(world, pos, state, direction);
|
||||
BlockState otherState = world.getBlockState(pos.offset(direction));
|
||||
if (state.getBlock() instanceof AxisPipeBlock && otherState.getBlock() instanceof AxisPipeBlock) {
|
||||
if (state.get(AxisPipeBlock.AXIS) == otherState.get(AxisPipeBlock.AXIS)) {
|
||||
if (state.getBlock() == otherState.getBlock()
|
||||
|| direction.getAxisDirection() == AxisDirection.POSITIVE)
|
||||
return AttachmentTypes.NONE;
|
||||
}
|
||||
}
|
||||
return attachment;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package com.simibubi.create.content.contraptions.fluids.pipes;
|
||||
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import com.simibubi.create.content.contraptions.fluids.FluidPipeBehaviour;
|
||||
import com.simibubi.create.foundation.fluid.FluidRenderer;
|
||||
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||
import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
import com.simibubi.create.foundation.utility.LerpedFloat;
|
||||
import com.simibubi.create.foundation.utility.Pair;
|
||||
|
||||
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
||||
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
|
||||
public class TransparentStraightPipeRenderer extends SafeTileEntityRenderer<StraightPipeTileEntity> {
|
||||
|
||||
public TransparentStraightPipeRenderer(TileEntityRendererDispatcher dispatcher) {
|
||||
super(dispatcher);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSafe(StraightPipeTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer,
|
||||
int light, int overlay) {
|
||||
FluidPipeBehaviour pipe = TileEntityBehaviour.get(te, FluidPipeBehaviour.TYPE);
|
||||
if (pipe == null)
|
||||
return;
|
||||
FluidStack fluidStack = pipe.getFluid();
|
||||
if (fluidStack.isEmpty())
|
||||
return;
|
||||
|
||||
for (Direction side : Iterate.directions) {
|
||||
if (!pipe.isConnectedTo(te.getBlockState(), side))
|
||||
continue;
|
||||
Pair<Boolean, LerpedFloat> strogestFlow = pipe.getStrogestFlow(side);
|
||||
if (strogestFlow == null)
|
||||
continue;
|
||||
LerpedFloat second = strogestFlow.getSecond();
|
||||
if (second == null)
|
||||
continue;
|
||||
|
||||
float value = second.getValue(partialTicks);
|
||||
Boolean inbound = strogestFlow.getFirst();
|
||||
if (value == 1 && !inbound) {
|
||||
FluidPipeBehaviour adjacent = TileEntityBehaviour.get(te.getWorld(), te.getPos()
|
||||
.offset(side), FluidPipeBehaviour.TYPE);
|
||||
|
||||
if (adjacent != null && adjacent.getFluid()
|
||||
.isEmpty())
|
||||
value -= 1e-6f;
|
||||
}
|
||||
|
||||
FluidRenderer.renderFluidStream(fluidStack, side, 3 / 16f, value, inbound, buffer, ms, light);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package com.simibubi.create.content.contraptions.fluids;
|
||||
package com.simibubi.create.content.contraptions.fluids.tank;
|
||||
|
||||
import com.simibubi.create.AllTileEntities;
|
||||
import com.simibubi.create.content.contraptions.wrench.IWrenchable;
|
||||
|
@ -182,7 +182,7 @@ public class FluidTankBlock extends Block implements IWrenchable, ITE<FluidTankT
|
|||
return ActionResultType.SUCCESS;
|
||||
}
|
||||
|
||||
controllerTE.sendData();
|
||||
controllerTE.sendDataImmediately();
|
||||
controllerTE.markDirty();
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package com.simibubi.create.content.contraptions.fluids;
|
||||
package com.simibubi.create.content.contraptions.fluids.tank;
|
||||
|
||||
import com.simibubi.create.foundation.block.connected.CTSpriteShiftEntry;
|
||||
import com.simibubi.create.foundation.block.connected.HorizontalCTBehaviour;
|
|
@ -1,4 +1,4 @@
|
|||
package com.simibubi.create.content.contraptions.fluids;
|
||||
package com.simibubi.create.content.contraptions.fluids.tank;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
|
@ -276,6 +276,7 @@ public class FluidTankConnectivityHandler {
|
|||
}
|
||||
}
|
||||
|
||||
te.fluidCapability.invalidate();
|
||||
if (tryReconnect)
|
||||
formTanks(world, cache == null ? new TankSearchCache() : cache, frontier);
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
package com.simibubi.create.content.contraptions.fluids;
|
||||
package com.simibubi.create.content.contraptions.fluids.tank;
|
||||
|
||||
import com.simibubi.create.content.contraptions.fluids.FluidTankBlock.Shape;
|
||||
import com.simibubi.create.content.contraptions.fluids.tank.FluidTankBlock.Shape;
|
||||
import com.simibubi.create.foundation.data.AssetLookup;
|
||||
import com.simibubi.create.foundation.data.SpecialBlockStateGen;
|
||||
import com.tterrag.registrate.providers.DataGenContext;
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue