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

This commit is contained in:
simibubi 2020-11-06 20:49:00 +01:00
commit 0a98171384
110 changed files with 3780 additions and 623 deletions

View file

@ -225,6 +225,7 @@ debef0f5dde74103aaf4422de4bc90e4099b0c47 assets/create/blockstates/mechanical_pl
92269fe66d7b83095a2e04e121af0be792f55dd6 assets/create/blockstates/mechanical_press.json
b7c4a0ff0c6f16e14d71fc0fb7fc66d032b65cf3 assets/create/blockstates/mechanical_pump.json
264d72320ee0f1e014319f7d99dcc1fa953a4ad4 assets/create/blockstates/mechanical_saw.json
94bbcb7e622471dbf418d78f9200ad321c7168de assets/create/blockstates/metal_bracket.json
4e48ad0936647065c2322390e7c0fe115c853a98 assets/create/blockstates/millstone.json
468202df0802e17c75fcad0993daf1bc5300ca91 assets/create/blockstates/minecart_anchor.json
6a42f86aaff8ced70aaa6adb9460614ab40c21e5 assets/create/blockstates/mossy_andesite.json
@ -384,22 +385,23 @@ c77b46d8b459e5c7cc495393546f3fcca8a1fa1d assets/create/blockstates/weathered_lim
4647010162eb4c350fad236d860317eaa1884c77 assets/create/blockstates/white_seat.json
89000903d0ab8139e919abea7aa0361b34c24e55 assets/create/blockstates/white_valve_handle.json
c4cd1131113667da0180898b5db3ebad609db8ba assets/create/blockstates/windmill_bearing.json
d4f804f2818376950ef28fc8d6250419f4e12218 assets/create/blockstates/wooden_bracket.json
e03c48512967845fce09d84b955d3bc7b480fedc assets/create/blockstates/yellow_sail.json
a3a11524cd3515fc01d905767b4b7ea782adaf03 assets/create/blockstates/yellow_seat.json
6801fa1f466f172700e573e5b8ee8ee5f9ca4583 assets/create/blockstates/yellow_valve_handle.json
7f39521b211441f5c3e06d60c5978cebe16cacfb assets/create/blockstates/zinc_block.json
b7181bcd8182b2f17088e5aa881f374c9c65470c assets/create/blockstates/zinc_ore.json
6fe6c50ae75a9c89c90d3423bc74f3e628bc213a assets/create/lang/en_ud.json
b054eb6cf72ac04fbb2512569effa84768adef74 assets/create/lang/en_us.json
cf432c7dcf9b91769a570242a59c12ecca79a091 assets/create/lang/unfinished/de_de.json
5a2e2499696f45b1f95feeaa702119b8e1b371eb assets/create/lang/unfinished/fr_fr.json
12ac01a6f21c536aa09599c36139f593cbbf7d1f assets/create/lang/unfinished/it_it.json
3e65e163c658e4f34124807716b009e1907187cc assets/create/lang/unfinished/ja_jp.json
4dfeba1d56d8ad688442d2ca026dfa16147178ef assets/create/lang/unfinished/ko_kr.json
3d114a874d1c198ecf0978fd13b98249536cc684 assets/create/lang/unfinished/nl_nl.json
3434f2d429bdf64dcbc915c0365e20250b64d819 assets/create/lang/unfinished/pt_br.json
0bfd9476411fc565a3011ffc43eecaca3f0e53ff assets/create/lang/unfinished/ru_ru.json
d7150e9c65d74f41e2dc65daadf003dc200e512c assets/create/lang/unfinished/zh_cn.json
be82e2e68c74c572e72979a6d4a5ec5e571931e2 assets/create/lang/en_ud.json
b953a264ec3044b955431fb988c0bafcb9b57388 assets/create/lang/en_us.json
97fe71d544f1bc7552e6c9d1f328ae02cb1a1947 assets/create/lang/unfinished/de_de.json
052819c4d2177bfc5cee9675300866d724f4b63f assets/create/lang/unfinished/fr_fr.json
67d67f305c83e021e2ae37e03b9bf4aa2661bc87 assets/create/lang/unfinished/it_it.json
b0e3fc5a71b5127b832e38daece78ca9db9ce303 assets/create/lang/unfinished/ja_jp.json
610f399864dfa9d7fd258570853f7d577c5aee31 assets/create/lang/unfinished/ko_kr.json
12215221adcb015c5c74dbfe5affa920cd570580 assets/create/lang/unfinished/nl_nl.json
ead7216188692e96fb060b35213f1ef6b0682e87 assets/create/lang/unfinished/pt_br.json
e9d95034f9b33eb8e41792740ed2d8c488af6676 assets/create/lang/unfinished/ru_ru.json
32a2c4af9a5247f3bc7a5c2f502376e1e580d8bc assets/create/lang/unfinished/zh_cn.json
487a511a01b2a4531fb672f917922312db78f958 assets/create/models/block/acacia_window.json
b48060cba1a382f373a05bf0039054053eccf076 assets/create/models/block/acacia_window_pane_noside.json
3066db1bf03cffa1a9c7fbacf47ae586632f4eb3 assets/create/models/block/acacia_window_pane_noside_alt.json
@ -469,6 +471,18 @@ dbfd2a996820d885d9741a3f168aa36c3538cfbd assets/create/models/block/birch_window
d876627b6e519c6f3f59c7c27cc7b0f903206f7c assets/create/models/block/blue_sail.json
e58b00a7222152d7facbe0e82f00933b974df747 assets/create/models/block/blue_seat.json
c7f91468b196fbda137e6b31764870b3bbfda6b6 assets/create/models/block/blue_valve_handle.json
213e99062a7f2a5e7464082d7975066bc6fc45e0 assets/create/models/block/bracket/cog/ground_metal.json
16e824026066d930187d812e77e2e582c0d3c1cc assets/create/models/block/bracket/cog/ground_wooden.json
8c22623c9565c66346600c0ccf9648c77c4a5870 assets/create/models/block/bracket/cog/wall_metal.json
3a9fc3d3f30af61b2db0cfdf365ec8d01f78f9b4 assets/create/models/block/bracket/cog/wall_wooden.json
f545a7631bce14e75c0a7df0baef00f9163c91d6 assets/create/models/block/bracket/pipe/ground_metal.json
ef4f1a0f5499674d5b3de8e584f380074c1ecb24 assets/create/models/block/bracket/pipe/ground_wooden.json
1de8d82b6355ab0028e7259ada0cc7a28bb0509b assets/create/models/block/bracket/pipe/wall_metal.json
6b8e7f992f6be00c22bda0dbeb71c3979c6ae903 assets/create/models/block/bracket/pipe/wall_wooden.json
c86a455b8e85ef190261718726b344cf15ba1e4f assets/create/models/block/bracket/shaft/ground_metal.json
8fa9ce896412af894d7c431a50104445d91b1d4d assets/create/models/block/bracket/shaft/ground_wooden.json
3956168840aca9425d3bf240650406c1dbc8ea66 assets/create/models/block/bracket/shaft/wall_metal.json
7aaa2fbdb618e8aab7e0da19a5393e1eaa608623 assets/create/models/block/bracket/shaft/wall_wooden.json
24dff9a8d22c9a88286d2b7d08384ac9f281a512 assets/create/models/block/brass_belt_funnel_pull_extended.json
c9c5f53c9d4f6cf6f509452e91cab1ba5b57f807 assets/create/models/block/brass_belt_funnel_pull_powered_extended.json
addcf821a2348c0985bf9a72229355cfab818069 assets/create/models/block/brass_belt_funnel_pull_powered_retracted.json
@ -1368,6 +1382,7 @@ f8d0d4b2a890ea7a69ab0c390947b48fe0478d3f assets/create/models/item/mechanical_pi
6c2acb80e53256fbb85f76851f335f9248ace6da assets/create/models/item/mechanical_press.json
4e363477e3e8059dd7b2bad04046521b31923d1b assets/create/models/item/mechanical_pump.json
3fc1fcb2016d2782c3667c21575423122b66705a assets/create/models/item/mechanical_saw.json
3afa723a8ba4160a4bd8778a56e1880e7ff53ed9 assets/create/models/item/metal_bracket.json
0eb5726c8c0de462f432411c210d6132b2c446a4 assets/create/models/item/millstone.json
363c5a2b8ac945b676c838cdf7b0494c3ab13599 assets/create/models/item/minecart_contraption.json
01e3fda31e549a3b6a1e5e615b59478e8f06f16a assets/create/models/item/minecart_coupling.json
@ -1538,6 +1553,7 @@ c6253e0f8db3c3992d3f78fe5045e276d39d5b22 assets/create/models/item/white_sail.js
69328eb4f91c4407fbcad5e3c4b88363f1a9572c assets/create/models/item/white_seat.json
be7a2d59d43083d7f2427193dcb9d68004224dd3 assets/create/models/item/white_valve_handle.json
d080b1b25e5bc8baf5aee68691b08c7f12ece3b0 assets/create/models/item/windmill_bearing.json
500abf752654a904d78a967f6c6d29a75a4821ab assets/create/models/item/wooden_bracket.json
2527b52413965a3e84b4718e08a9b8bb30a741ea assets/create/models/item/wrench.json
4b49bc2418410cded5f0b7da3430f1a22e049f18 assets/create/models/item/yellow_seat.json
790daf016f980801e7587b548a325082c65f6f03 assets/create/models/item/yellow_valve_handle.json
@ -1665,6 +1681,7 @@ b2845089f6356957e048df29ea75c9f5e64d5a44 data/create/advancements/recipes/create
02cfc8c25c2977292dba992542c83666d9123e95 data/create/advancements/recipes/create.base/crafting/kinetics/mechanical_press.json
750d93013709081b7eaca5a5b9122ab51ab31d02 data/create/advancements/recipes/create.base/crafting/kinetics/mechanical_pump.json
f5ea782327d2353dd0e484b15536b7c19987a32b data/create/advancements/recipes/create.base/crafting/kinetics/mechanical_saw.json
8fd1bd08e678262d95ac97ba2f18d631c2fd3796 data/create/advancements/recipes/create.base/crafting/kinetics/metal_bracket.json
5a107ee1772727b66414c8d143b77833f3a92f0f data/create/advancements/recipes/create.base/crafting/kinetics/millstone.json
d38e8ff9dd33558227678d69393b57a360caa28e data/create/advancements/recipes/create.base/crafting/kinetics/mysterious_cuckoo_clock.json
afeb2a152697b68bc953986d6886cbe527c6d2b5 data/create/advancements/recipes/create.base/crafting/kinetics/nozzle.json
@ -1706,6 +1723,7 @@ f876dcbd2877c921613a4af481c89d66664c1ea8 data/create/advancements/recipes/create
856760c4b120f7b29a94dd22fe04d62df061d409 data/create/advancements/recipes/create.base/crafting/kinetics/white_seat_from_other_seat.json
b73e6f8b89e6ef94167b6fa3d0837a27222edb01 data/create/advancements/recipes/create.base/crafting/kinetics/white_valve_handle_from_other_valve_handle.json
6b783787a32446a39bb553359a7db58f71492a42 data/create/advancements/recipes/create.base/crafting/kinetics/windmill_bearing.json
d3874ab405cc09b75f5e4ff2994e9ddd9b5e77f6 data/create/advancements/recipes/create.base/crafting/kinetics/wooden_bracket.json
ddbe7ae23f48dcaee3ad44a0e597c24380b51682 data/create/advancements/recipes/create.base/crafting/kinetics/wrench.json
14c1cac4545f544a78bfd80cf7dd6355794c6679 data/create/advancements/recipes/create.base/crafting/kinetics/yellow_seat.json
e8c2001863d9819d2a2c1fddeda41a4f126a5c09 data/create/advancements/recipes/create.base/crafting/kinetics/yellow_seat_from_other_seat.json
@ -2390,6 +2408,7 @@ d9e217fcc668a04ee495968f8ccf9966271b6cea data/create/loot_tables/blocks/mechanic
0e0742d066bda87ba5cc835a4028efb99e70b2f2 data/create/loot_tables/blocks/mechanical_press.json
e94a78187bcf7f235244b2c656732ba9a5821dd0 data/create/loot_tables/blocks/mechanical_pump.json
321daee16d6fad25ecc84da1b2830556d67e2a19 data/create/loot_tables/blocks/mechanical_saw.json
b13066b9e627db6954a30b115908602f1298576b data/create/loot_tables/blocks/metal_bracket.json
efbd4689e7d6740b80357203d1e02196f0752efa data/create/loot_tables/blocks/millstone.json
205f5899101262f31f5c1a88bb7d954918d08d04 data/create/loot_tables/blocks/minecart_anchor.json
53215ac772bee2f88052266b82213aaf668660e9 data/create/loot_tables/blocks/mossy_andesite.json
@ -2549,6 +2568,7 @@ e8f3af61d9a2fd1ff5b32c9bb474ed005e6d70c4 data/create/loot_tables/blocks/weathere
969eda31556feb5a68e350762848d17453275fee data/create/loot_tables/blocks/white_seat.json
79fe374f8e677088f928a3a49ff5eeed6128d165 data/create/loot_tables/blocks/white_valve_handle.json
941ea78ea7c0f0061c3d3569ecea333ae6a16bf1 data/create/loot_tables/blocks/windmill_bearing.json
728c8719e653825c030913df94ce845fdc6d79b7 data/create/loot_tables/blocks/wooden_bracket.json
28ae0ee8a0b1fb6becae6264de687fe17940708e data/create/loot_tables/blocks/yellow_sail.json
37ead431a278928a09b260ae06a448e2c791a73e data/create/loot_tables/blocks/yellow_seat.json
899bb208908a2f9bec5e544ff47526f3e24db720 data/create/loot_tables/blocks/yellow_valve_handle.json
@ -2671,6 +2691,7 @@ ac9003ad3320fe2009c1793a3c6e86bdf20ca832 data/create/recipes/crafting/kinetics/m
ce8e269907aae5549cea04141bd231f4a20e6453 data/create/recipes/crafting/kinetics/mechanical_press.json
5a685078d3c9d7dbe68080b7b6f2a44fc41582c5 data/create/recipes/crafting/kinetics/mechanical_pump.json
ce28bcb47a379976d4a1bdfcfd1cdd0bae0bcdae data/create/recipes/crafting/kinetics/mechanical_saw.json
353146e9501096b4cd9632ad5500b0a2406c6f5d data/create/recipes/crafting/kinetics/metal_bracket.json
58d9046e61eae40958181388186a35dc07cc9a59 data/create/recipes/crafting/kinetics/millstone.json
13fa2887d3c988973c9222ce5e2e3dd0d9bd8374 data/create/recipes/crafting/kinetics/minecart_from_contraption_cart.json
be4c7fdb0ba1e9ee6d3dcf200dc2718ad83ec8fb data/create/recipes/crafting/kinetics/mysterious_cuckoo_clock.json
@ -2713,6 +2734,7 @@ f4d88aa2edea548d29cf2678a111d8bb5db7720a data/create/recipes/crafting/kinetics/w
7e0d276cd56f04f35d02c25810bffdf8fc297fcd data/create/recipes/crafting/kinetics/white_seat_from_other_seat.json
4d3890621caa0bdbb752a395c1f5761dbbc1121e data/create/recipes/crafting/kinetics/white_valve_handle_from_other_valve_handle.json
8508255518d3718a0d8c2f536f69ffe9ed48a855 data/create/recipes/crafting/kinetics/windmill_bearing.json
d11eee4005372b1d0fad283b28c8016d823b5e37 data/create/recipes/crafting/kinetics/wooden_bracket.json
3ec8bb5660656f1c676035d8ba5460462c1d1865 data/create/recipes/crafting/kinetics/wrench.json
5579e58473474c4e59efd1ee39ddf0140d66b618 data/create/recipes/crafting/kinetics/yellow_seat.json
f055d233ac7ee9eac840a658afa01bedd793ff38 data/create/recipes/crafting/kinetics/yellow_seat_from_other_seat.json

View file

@ -0,0 +1,154 @@
{
"variants": {
"axis_along_first=false,facing=down,type=pipe": {
"model": "create:block/bracket/pipe/ground_metal",
"x": 180
},
"axis_along_first=true,facing=down,type=pipe": {
"model": "create:block/bracket/pipe/ground_metal",
"x": 180,
"y": 90
},
"axis_along_first=false,facing=up,type=pipe": {
"model": "create:block/bracket/pipe/ground_metal"
},
"axis_along_first=true,facing=up,type=pipe": {
"model": "create:block/bracket/pipe/ground_metal",
"y": 90
},
"axis_along_first=false,facing=north,type=pipe": {
"model": "create:block/bracket/pipe/wall_metal",
"x": 90,
"y": 270
},
"axis_along_first=true,facing=north,type=pipe": {
"model": "create:block/bracket/pipe/wall_metal",
"y": 270
},
"axis_along_first=false,facing=south,type=pipe": {
"model": "create:block/bracket/pipe/wall_metal",
"x": 90,
"y": 90
},
"axis_along_first=true,facing=south,type=pipe": {
"model": "create:block/bracket/pipe/wall_metal",
"y": 90
},
"axis_along_first=false,facing=west,type=pipe": {
"model": "create:block/bracket/pipe/wall_metal",
"y": 180
},
"axis_along_first=true,facing=west,type=pipe": {
"model": "create:block/bracket/pipe/wall_metal",
"x": 90,
"y": 180
},
"axis_along_first=false,facing=east,type=pipe": {
"model": "create:block/bracket/pipe/wall_metal"
},
"axis_along_first=true,facing=east,type=pipe": {
"model": "create:block/bracket/pipe/wall_metal",
"x": 90
},
"axis_along_first=false,facing=down,type=cog": {
"model": "create:block/bracket/cog/ground_metal",
"x": 180
},
"axis_along_first=true,facing=down,type=cog": {
"model": "create:block/bracket/cog/ground_metal",
"x": 180,
"y": 90
},
"axis_along_first=false,facing=up,type=cog": {
"model": "create:block/bracket/cog/ground_metal"
},
"axis_along_first=true,facing=up,type=cog": {
"model": "create:block/bracket/cog/ground_metal",
"y": 90
},
"axis_along_first=false,facing=north,type=cog": {
"model": "create:block/bracket/cog/wall_metal",
"x": 90,
"y": 270
},
"axis_along_first=true,facing=north,type=cog": {
"model": "create:block/bracket/cog/wall_metal",
"y": 270
},
"axis_along_first=false,facing=south,type=cog": {
"model": "create:block/bracket/cog/wall_metal",
"x": 90,
"y": 90
},
"axis_along_first=true,facing=south,type=cog": {
"model": "create:block/bracket/cog/wall_metal",
"y": 90
},
"axis_along_first=false,facing=west,type=cog": {
"model": "create:block/bracket/cog/wall_metal",
"y": 180
},
"axis_along_first=true,facing=west,type=cog": {
"model": "create:block/bracket/cog/wall_metal",
"x": 90,
"y": 180
},
"axis_along_first=false,facing=east,type=cog": {
"model": "create:block/bracket/cog/wall_metal"
},
"axis_along_first=true,facing=east,type=cog": {
"model": "create:block/bracket/cog/wall_metal",
"x": 90
},
"axis_along_first=false,facing=down,type=shaft": {
"model": "create:block/bracket/shaft/ground_metal",
"x": 180
},
"axis_along_first=true,facing=down,type=shaft": {
"model": "create:block/bracket/shaft/ground_metal",
"x": 180,
"y": 90
},
"axis_along_first=false,facing=up,type=shaft": {
"model": "create:block/bracket/shaft/ground_metal"
},
"axis_along_first=true,facing=up,type=shaft": {
"model": "create:block/bracket/shaft/ground_metal",
"y": 90
},
"axis_along_first=false,facing=north,type=shaft": {
"model": "create:block/bracket/shaft/wall_metal",
"x": 90,
"y": 270
},
"axis_along_first=true,facing=north,type=shaft": {
"model": "create:block/bracket/shaft/wall_metal",
"y": 270
},
"axis_along_first=false,facing=south,type=shaft": {
"model": "create:block/bracket/shaft/wall_metal",
"x": 90,
"y": 90
},
"axis_along_first=true,facing=south,type=shaft": {
"model": "create:block/bracket/shaft/wall_metal",
"y": 90
},
"axis_along_first=false,facing=west,type=shaft": {
"model": "create:block/bracket/shaft/wall_metal",
"y": 180
},
"axis_along_first=true,facing=west,type=shaft": {
"model": "create:block/bracket/shaft/wall_metal",
"x": 90,
"y": 180
},
"axis_along_first=false,facing=east,type=shaft": {
"model": "create:block/bracket/shaft/wall_metal"
},
"axis_along_first=true,facing=east,type=shaft": {
"model": "create:block/bracket/shaft/wall_metal",
"x": 90
}
}
}

View file

@ -0,0 +1,154 @@
{
"variants": {
"axis_along_first=false,facing=down,type=pipe": {
"model": "create:block/bracket/pipe/ground_wooden",
"x": 180
},
"axis_along_first=true,facing=down,type=pipe": {
"model": "create:block/bracket/pipe/ground_wooden",
"x": 180,
"y": 90
},
"axis_along_first=false,facing=up,type=pipe": {
"model": "create:block/bracket/pipe/ground_wooden"
},
"axis_along_first=true,facing=up,type=pipe": {
"model": "create:block/bracket/pipe/ground_wooden",
"y": 90
},
"axis_along_first=false,facing=north,type=pipe": {
"model": "create:block/bracket/pipe/wall_wooden",
"x": 90,
"y": 270
},
"axis_along_first=true,facing=north,type=pipe": {
"model": "create:block/bracket/pipe/wall_wooden",
"y": 270
},
"axis_along_first=false,facing=south,type=pipe": {
"model": "create:block/bracket/pipe/wall_wooden",
"x": 90,
"y": 90
},
"axis_along_first=true,facing=south,type=pipe": {
"model": "create:block/bracket/pipe/wall_wooden",
"y": 90
},
"axis_along_first=false,facing=west,type=pipe": {
"model": "create:block/bracket/pipe/wall_wooden",
"y": 180
},
"axis_along_first=true,facing=west,type=pipe": {
"model": "create:block/bracket/pipe/wall_wooden",
"x": 90,
"y": 180
},
"axis_along_first=false,facing=east,type=pipe": {
"model": "create:block/bracket/pipe/wall_wooden"
},
"axis_along_first=true,facing=east,type=pipe": {
"model": "create:block/bracket/pipe/wall_wooden",
"x": 90
},
"axis_along_first=false,facing=down,type=cog": {
"model": "create:block/bracket/cog/ground_wooden",
"x": 180
},
"axis_along_first=true,facing=down,type=cog": {
"model": "create:block/bracket/cog/ground_wooden",
"x": 180,
"y": 90
},
"axis_along_first=false,facing=up,type=cog": {
"model": "create:block/bracket/cog/ground_wooden"
},
"axis_along_first=true,facing=up,type=cog": {
"model": "create:block/bracket/cog/ground_wooden",
"y": 90
},
"axis_along_first=false,facing=north,type=cog": {
"model": "create:block/bracket/cog/wall_wooden",
"x": 90,
"y": 270
},
"axis_along_first=true,facing=north,type=cog": {
"model": "create:block/bracket/cog/wall_wooden",
"y": 270
},
"axis_along_first=false,facing=south,type=cog": {
"model": "create:block/bracket/cog/wall_wooden",
"x": 90,
"y": 90
},
"axis_along_first=true,facing=south,type=cog": {
"model": "create:block/bracket/cog/wall_wooden",
"y": 90
},
"axis_along_first=false,facing=west,type=cog": {
"model": "create:block/bracket/cog/wall_wooden",
"y": 180
},
"axis_along_first=true,facing=west,type=cog": {
"model": "create:block/bracket/cog/wall_wooden",
"x": 90,
"y": 180
},
"axis_along_first=false,facing=east,type=cog": {
"model": "create:block/bracket/cog/wall_wooden"
},
"axis_along_first=true,facing=east,type=cog": {
"model": "create:block/bracket/cog/wall_wooden",
"x": 90
},
"axis_along_first=false,facing=down,type=shaft": {
"model": "create:block/bracket/shaft/ground_wooden",
"x": 180
},
"axis_along_first=true,facing=down,type=shaft": {
"model": "create:block/bracket/shaft/ground_wooden",
"x": 180,
"y": 90
},
"axis_along_first=false,facing=up,type=shaft": {
"model": "create:block/bracket/shaft/ground_wooden"
},
"axis_along_first=true,facing=up,type=shaft": {
"model": "create:block/bracket/shaft/ground_wooden",
"y": 90
},
"axis_along_first=false,facing=north,type=shaft": {
"model": "create:block/bracket/shaft/wall_wooden",
"x": 90,
"y": 270
},
"axis_along_first=true,facing=north,type=shaft": {
"model": "create:block/bracket/shaft/wall_wooden",
"y": 270
},
"axis_along_first=false,facing=south,type=shaft": {
"model": "create:block/bracket/shaft/wall_wooden",
"x": 90,
"y": 90
},
"axis_along_first=true,facing=south,type=shaft": {
"model": "create:block/bracket/shaft/wall_wooden",
"y": 90
},
"axis_along_first=false,facing=west,type=shaft": {
"model": "create:block/bracket/shaft/wall_wooden",
"y": 180
},
"axis_along_first=true,facing=west,type=shaft": {
"model": "create:block/bracket/shaft/wall_wooden",
"x": 90,
"y": 180
},
"axis_along_first=false,facing=east,type=shaft": {
"model": "create:block/bracket/shaft/wall_wooden"
},
"axis_along_first=true,facing=east,type=shaft": {
"model": "create:block/bracket/shaft/wall_wooden",
"x": 90
}
}
}

View file

@ -226,6 +226,7 @@
"block.create.mechanical_press": "ss\u01DD\u0279\u0500 \u05DF\u0250\u0254\u0131u\u0250\u0265\u0254\u01DDW",
"block.create.mechanical_pump": "d\u026Fn\u0500 \u05DF\u0250\u0254\u0131u\u0250\u0265\u0254\u01DDW",
"block.create.mechanical_saw": "\u028D\u0250S \u05DF\u0250\u0254\u0131u\u0250\u0265\u0254\u01DDW",
"block.create.metal_bracket": "\u0287\u01DD\u029E\u0254\u0250\u0279\u15FA \u05DF\u0250\u0287\u01DDW",
"block.create.millstone": "\u01DDuo\u0287s\u05DF\u05DF\u0131W",
"block.create.minecart_anchor": "\u0279o\u0265\u0254u\u2C6F \u0287\u0279\u0250\u0254\u01DDu\u0131W",
"block.create.mossy_andesite": "\u01DD\u0287\u0131s\u01DDpu\u2C6F \u028EssoW",
@ -385,6 +386,7 @@
"block.create.white_seat": "\u0287\u0250\u01DDS \u01DD\u0287\u0131\u0265M",
"block.create.white_valve_handle": "\u01DD\u05DFpu\u0250H \u01DD\u028C\u05DF\u0250\u039B \u01DD\u0287\u0131\u0265M",
"block.create.windmill_bearing": "bu\u0131\u0279\u0250\u01DD\u15FA \u05DF\u05DF\u0131\u026Fpu\u0131M",
"block.create.wooden_bracket": "\u0287\u01DD\u029E\u0254\u0250\u0279\u15FA u\u01DDpooM",
"block.create.yellow_sail": "\u05DF\u0131\u0250S \u028Do\u05DF\u05DF\u01DD\u028E",
"block.create.yellow_seat": "\u0287\u0250\u01DDS \u028Do\u05DF\u05DF\u01DD\u028E",
"block.create.yellow_valve_handle": "\u01DD\u05DFpu\u0250H \u01DD\u028C\u05DF\u0250\u039B \u028Do\u05DF\u05DF\u01DD\u028E",

View file

@ -229,6 +229,7 @@
"block.create.mechanical_press": "Mechanical Press",
"block.create.mechanical_pump": "Mechanical Pump",
"block.create.mechanical_saw": "Mechanical Saw",
"block.create.metal_bracket": "Metal Bracket",
"block.create.millstone": "Millstone",
"block.create.minecart_anchor": "Minecart Anchor",
"block.create.mossy_andesite": "Mossy Andesite",
@ -388,6 +389,7 @@
"block.create.white_seat": "White Seat",
"block.create.white_valve_handle": "White Valve Handle",
"block.create.windmill_bearing": "Windmill Bearing",
"block.create.wooden_bracket": "Wooden Bracket",
"block.create.yellow_sail": "Yellow Sail",
"block.create.yellow_seat": "Yellow Seat",
"block.create.yellow_valve_handle": "Yellow Valve Handle",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 1024",
"_": "Missing Localizations: 1026",
"_": "->------------------------] Game Elements [------------------------<-",
@ -230,6 +230,7 @@
"block.create.mechanical_press": "Mechanische Presse",
"block.create.mechanical_pump": "UNLOCALIZED: Mechanical Pump",
"block.create.mechanical_saw": "UNLOCALIZED: Mechanical Saw",
"block.create.metal_bracket": "UNLOCALIZED: Metal Bracket",
"block.create.millstone": "UNLOCALIZED: Millstone",
"block.create.minecart_anchor": "UNLOCALIZED: Minecart Anchor",
"block.create.mossy_andesite": "UNLOCALIZED: Mossy Andesite",
@ -389,6 +390,7 @@
"block.create.white_seat": "UNLOCALIZED: White Seat",
"block.create.white_valve_handle": "UNLOCALIZED: White Valve Handle",
"block.create.windmill_bearing": "UNLOCALIZED: Windmill Bearing",
"block.create.wooden_bracket": "UNLOCALIZED: Wooden Bracket",
"block.create.yellow_sail": "UNLOCALIZED: Yellow Sail",
"block.create.yellow_seat": "UNLOCALIZED: Yellow Seat",
"block.create.yellow_valve_handle": "UNLOCALIZED: Yellow Valve Handle",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 653",
"_": "Missing Localizations: 655",
"_": "->------------------------] Game Elements [------------------------<-",
@ -230,6 +230,7 @@
"block.create.mechanical_press": "Presse mécanique",
"block.create.mechanical_pump": "UNLOCALIZED: Mechanical Pump",
"block.create.mechanical_saw": "Scie mécanique",
"block.create.metal_bracket": "UNLOCALIZED: Metal Bracket",
"block.create.millstone": "UNLOCALIZED: Millstone",
"block.create.minecart_anchor": "UNLOCALIZED: Minecart Anchor",
"block.create.mossy_andesite": "UNLOCALIZED: Mossy Andesite",
@ -389,6 +390,7 @@
"block.create.white_seat": "UNLOCALIZED: White Seat",
"block.create.white_valve_handle": "UNLOCALIZED: White Valve Handle",
"block.create.windmill_bearing": "UNLOCALIZED: Windmill Bearing",
"block.create.wooden_bracket": "UNLOCALIZED: Wooden Bracket",
"block.create.yellow_sail": "UNLOCALIZED: Yellow Sail",
"block.create.yellow_seat": "UNLOCALIZED: Yellow Seat",
"block.create.yellow_valve_handle": "UNLOCALIZED: Yellow Valve Handle",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 637",
"_": "Missing Localizations: 639",
"_": "->------------------------] Game Elements [------------------------<-",
@ -230,6 +230,7 @@
"block.create.mechanical_press": "Pressa Meccanica",
"block.create.mechanical_pump": "UNLOCALIZED: Mechanical Pump",
"block.create.mechanical_saw": "Sega Meccanica",
"block.create.metal_bracket": "UNLOCALIZED: Metal Bracket",
"block.create.millstone": "Macina",
"block.create.minecart_anchor": "UNLOCALIZED: Minecart Anchor",
"block.create.mossy_andesite": "UNLOCALIZED: Mossy Andesite",
@ -389,6 +390,7 @@
"block.create.white_seat": "UNLOCALIZED: White Seat",
"block.create.white_valve_handle": "UNLOCALIZED: White Valve Handle",
"block.create.windmill_bearing": "UNLOCALIZED: Windmill Bearing",
"block.create.wooden_bracket": "UNLOCALIZED: Wooden Bracket",
"block.create.yellow_sail": "UNLOCALIZED: Yellow Sail",
"block.create.yellow_seat": "UNLOCALIZED: Yellow Seat",
"block.create.yellow_valve_handle": "UNLOCALIZED: Yellow Valve Handle",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 636",
"_": "Missing Localizations: 638",
"_": "->------------------------] Game Elements [------------------------<-",
@ -230,6 +230,7 @@
"block.create.mechanical_press": "メカニカルプレス",
"block.create.mechanical_pump": "UNLOCALIZED: Mechanical Pump",
"block.create.mechanical_saw": "メカニカル鋸",
"block.create.metal_bracket": "UNLOCALIZED: Metal Bracket",
"block.create.millstone": "石臼",
"block.create.minecart_anchor": "UNLOCALIZED: Minecart Anchor",
"block.create.mossy_andesite": "UNLOCALIZED: Mossy Andesite",
@ -389,6 +390,7 @@
"block.create.white_seat": "UNLOCALIZED: White Seat",
"block.create.white_valve_handle": "UNLOCALIZED: White Valve Handle",
"block.create.windmill_bearing": "UNLOCALIZED: Windmill Bearing",
"block.create.wooden_bracket": "UNLOCALIZED: Wooden Bracket",
"block.create.yellow_sail": "UNLOCALIZED: Yellow Sail",
"block.create.yellow_seat": "UNLOCALIZED: Yellow Seat",
"block.create.yellow_valve_handle": "UNLOCALIZED: Yellow Valve Handle",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 637",
"_": "Missing Localizations: 639",
"_": "->------------------------] Game Elements [------------------------<-",
@ -230,6 +230,7 @@
"block.create.mechanical_press": "압착기",
"block.create.mechanical_pump": "UNLOCALIZED: Mechanical Pump",
"block.create.mechanical_saw": "톱",
"block.create.metal_bracket": "UNLOCALIZED: Metal Bracket",
"block.create.millstone": "맷돌",
"block.create.minecart_anchor": "UNLOCALIZED: Minecart Anchor",
"block.create.mossy_andesite": "UNLOCALIZED: Mossy Andesite",
@ -389,6 +390,7 @@
"block.create.white_seat": "UNLOCALIZED: White Seat",
"block.create.white_valve_handle": "UNLOCALIZED: White Valve Handle",
"block.create.windmill_bearing": "UNLOCALIZED: Windmill Bearing",
"block.create.wooden_bracket": "UNLOCALIZED: Wooden Bracket",
"block.create.yellow_sail": "UNLOCALIZED: Yellow Sail",
"block.create.yellow_seat": "UNLOCALIZED: Yellow Seat",
"block.create.yellow_valve_handle": "UNLOCALIZED: Yellow Valve Handle",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 965",
"_": "Missing Localizations: 967",
"_": "->------------------------] Game Elements [------------------------<-",
@ -230,6 +230,7 @@
"block.create.mechanical_press": "Mechanische Pers",
"block.create.mechanical_pump": "UNLOCALIZED: Mechanical Pump",
"block.create.mechanical_saw": "Mechanische Zaag",
"block.create.metal_bracket": "UNLOCALIZED: Metal Bracket",
"block.create.millstone": "UNLOCALIZED: Millstone",
"block.create.minecart_anchor": "UNLOCALIZED: Minecart Anchor",
"block.create.mossy_andesite": "UNLOCALIZED: Mossy Andesite",
@ -389,6 +390,7 @@
"block.create.white_seat": "UNLOCALIZED: White Seat",
"block.create.white_valve_handle": "UNLOCALIZED: White Valve Handle",
"block.create.windmill_bearing": "UNLOCALIZED: Windmill Bearing",
"block.create.wooden_bracket": "UNLOCALIZED: Wooden Bracket",
"block.create.yellow_sail": "UNLOCALIZED: Yellow Sail",
"block.create.yellow_seat": "UNLOCALIZED: Yellow Seat",
"block.create.yellow_valve_handle": "UNLOCALIZED: Yellow Valve Handle",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 1031",
"_": "Missing Localizations: 1033",
"_": "->------------------------] Game Elements [------------------------<-",
@ -230,6 +230,7 @@
"block.create.mechanical_press": "Prensa Mecânico",
"block.create.mechanical_pump": "UNLOCALIZED: Mechanical Pump",
"block.create.mechanical_saw": "UNLOCALIZED: Mechanical Saw",
"block.create.metal_bracket": "UNLOCALIZED: Metal Bracket",
"block.create.millstone": "UNLOCALIZED: Millstone",
"block.create.minecart_anchor": "UNLOCALIZED: Minecart Anchor",
"block.create.mossy_andesite": "UNLOCALIZED: Mossy Andesite",
@ -389,6 +390,7 @@
"block.create.white_seat": "UNLOCALIZED: White Seat",
"block.create.white_valve_handle": "UNLOCALIZED: White Valve Handle",
"block.create.windmill_bearing": "UNLOCALIZED: Windmill Bearing",
"block.create.wooden_bracket": "UNLOCALIZED: Wooden Bracket",
"block.create.yellow_sail": "UNLOCALIZED: Yellow Sail",
"block.create.yellow_seat": "UNLOCALIZED: Yellow Seat",
"block.create.yellow_valve_handle": "UNLOCALIZED: Yellow Valve Handle",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 306",
"_": "Missing Localizations: 308",
"_": "->------------------------] Game Elements [------------------------<-",
@ -230,6 +230,7 @@
"block.create.mechanical_press": "Механический пресс",
"block.create.mechanical_pump": "UNLOCALIZED: Mechanical Pump",
"block.create.mechanical_saw": "Механическая пила",
"block.create.metal_bracket": "UNLOCALIZED: Metal Bracket",
"block.create.millstone": "Жернов",
"block.create.minecart_anchor": "Вагонеточный якорь",
"block.create.mossy_andesite": "Замшелый андезит",
@ -389,6 +390,7 @@
"block.create.white_seat": "UNLOCALIZED: White Seat",
"block.create.white_valve_handle": "UNLOCALIZED: White Valve Handle",
"block.create.windmill_bearing": "UNLOCALIZED: Windmill Bearing",
"block.create.wooden_bracket": "UNLOCALIZED: Wooden Bracket",
"block.create.yellow_sail": "UNLOCALIZED: Yellow Sail",
"block.create.yellow_seat": "UNLOCALIZED: Yellow Seat",
"block.create.yellow_valve_handle": "UNLOCALIZED: Yellow Valve Handle",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 319",
"_": "Missing Localizations: 321",
"_": "->------------------------] Game Elements [------------------------<-",
@ -230,6 +230,7 @@
"block.create.mechanical_press": "动力辊压机",
"block.create.mechanical_pump": "UNLOCALIZED: Mechanical Pump",
"block.create.mechanical_saw": "动力切割机",
"block.create.metal_bracket": "UNLOCALIZED: Metal Bracket",
"block.create.millstone": "石磨",
"block.create.minecart_anchor": "矿车锚",
"block.create.mossy_andesite": "生苔安山岩",
@ -389,6 +390,7 @@
"block.create.white_seat": "UNLOCALIZED: White Seat",
"block.create.white_valve_handle": "UNLOCALIZED: White Valve Handle",
"block.create.windmill_bearing": "UNLOCALIZED: Windmill Bearing",
"block.create.wooden_bracket": "UNLOCALIZED: Wooden Bracket",
"block.create.yellow_sail": "UNLOCALIZED: Yellow Sail",
"block.create.yellow_seat": "UNLOCALIZED: Yellow Seat",
"block.create.yellow_valve_handle": "UNLOCALIZED: Yellow Valve Handle",

View file

@ -0,0 +1,7 @@
{
"parent": "create:block/bracket/cog/ground",
"textures": {
"bracket": "create:block/bracket_metal",
"plate": "create:block/bracket_plate_metal"
}
}

View file

@ -0,0 +1,7 @@
{
"parent": "create:block/bracket/cog/ground",
"textures": {
"bracket": "create:block/bracket_wooden",
"plate": "create:block/bracket_plate_wooden"
}
}

View file

@ -0,0 +1,7 @@
{
"parent": "create:block/bracket/cog/wall",
"textures": {
"bracket": "create:block/bracket_metal",
"plate": "create:block/bracket_plate_metal"
}
}

View file

@ -0,0 +1,7 @@
{
"parent": "create:block/bracket/cog/wall",
"textures": {
"bracket": "create:block/bracket_wooden",
"plate": "create:block/bracket_plate_wooden"
}
}

View file

@ -0,0 +1,7 @@
{
"parent": "create:block/bracket/pipe/ground",
"textures": {
"bracket": "create:block/bracket_metal",
"plate": "create:block/bracket_plate_metal"
}
}

View file

@ -0,0 +1,7 @@
{
"parent": "create:block/bracket/pipe/ground",
"textures": {
"bracket": "create:block/bracket_wooden",
"plate": "create:block/bracket_plate_wooden"
}
}

View file

@ -0,0 +1,7 @@
{
"parent": "create:block/bracket/pipe/wall",
"textures": {
"bracket": "create:block/bracket_metal",
"plate": "create:block/bracket_plate_metal"
}
}

View file

@ -0,0 +1,7 @@
{
"parent": "create:block/bracket/pipe/wall",
"textures": {
"bracket": "create:block/bracket_wooden",
"plate": "create:block/bracket_plate_wooden"
}
}

View file

@ -0,0 +1,7 @@
{
"parent": "create:block/bracket/shaft/ground",
"textures": {
"bracket": "create:block/bracket_metal",
"plate": "create:block/bracket_plate_metal"
}
}

View file

@ -0,0 +1,7 @@
{
"parent": "create:block/bracket/shaft/ground",
"textures": {
"bracket": "create:block/bracket_wooden",
"plate": "create:block/bracket_plate_wooden"
}
}

View file

@ -0,0 +1,7 @@
{
"parent": "create:block/bracket/shaft/wall",
"textures": {
"bracket": "create:block/bracket_metal",
"plate": "create:block/bracket_plate_metal"
}
}

View file

@ -0,0 +1,7 @@
{
"parent": "create:block/bracket/shaft/wall",
"textures": {
"bracket": "create:block/bracket_wooden",
"plate": "create:block/bracket_plate_wooden"
}
}

View file

@ -0,0 +1,7 @@
{
"parent": "create:block/bracket/item",
"textures": {
"bracket": "create:block/bracket_metal",
"plate": "create:block/bracket_plate_metal"
}
}

View file

@ -0,0 +1,7 @@
{
"parent": "create:block/bracket/item",
"textures": {
"bracket": "create:block/bracket_wooden",
"plate": "create:block/bracket_plate_wooden"
}
}

View file

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

View file

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

View file

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

View file

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

View file

@ -0,0 +1,22 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"SSS",
"PCP"
],
"key": {
"S": {
"tag": "forge:nuggets/iron"
},
"P": {
"tag": "forge:ingots/iron"
},
"C": {
"item": "create:andesite_alloy"
}
},
"result": {
"item": "create:metal_bracket",
"count": 4
}
}

View file

@ -0,0 +1,22 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"SSS",
"PCP"
],
"key": {
"S": {
"tag": "forge:rods/wooden"
},
"P": {
"tag": "minecraft:planks"
},
"C": {
"item": "create:andesite_alloy"
}
},
"result": {
"item": "create:wooden_bracket",
"count": 4
}
}

View file

@ -68,6 +68,9 @@ import com.simibubi.create.content.contraptions.fluids.PumpBlock;
import com.simibubi.create.content.contraptions.fluids.actors.HosePulleyBlock;
import com.simibubi.create.content.contraptions.fluids.actors.ItemDrainBlock;
import com.simibubi.create.content.contraptions.fluids.actors.SpoutBlock;
import com.simibubi.create.content.contraptions.fluids.pipes.BracketBlock;
import com.simibubi.create.content.contraptions.fluids.pipes.BracketBlockItem;
import com.simibubi.create.content.contraptions.fluids.pipes.BracketGenerator;
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.FluidValveBlock;
@ -90,6 +93,7 @@ import com.simibubi.create.content.contraptions.relays.belt.BeltBlock;
import com.simibubi.create.content.contraptions.relays.belt.BeltColor;
import com.simibubi.create.content.contraptions.relays.belt.BeltGenerator;
import com.simibubi.create.content.contraptions.relays.belt.BeltModel;
import com.simibubi.create.content.contraptions.relays.elementary.BracketedKineticBlockModel;
import com.simibubi.create.content.contraptions.relays.elementary.CogWheelBlock;
import com.simibubi.create.content.contraptions.relays.elementary.CogwheelBlockItem;
import com.simibubi.create.content.contraptions.relays.elementary.ShaftBlock;
@ -206,6 +210,7 @@ public class AllBlocks {
.initialProperties(SharedProperties::stone)
.transform(StressConfigDefaults.setNoImpact())
.blockstate(BlockStateGen.axisBlockProvider(false))
.onRegister(CreateRegistrate.blockModel(() -> BracketedKineticBlockModel::new))
.simpleItem()
.register();
@ -214,6 +219,7 @@ public class AllBlocks {
.transform(StressConfigDefaults.setNoImpact())
.properties(p -> p.sound(SoundType.WOOD))
.blockstate(BlockStateGen.axisBlockProvider(false))
.onRegister(CreateRegistrate.blockModel(() -> BracketedKineticBlockModel::new))
.item(CogwheelBlockItem::new)
.build()
.register();
@ -224,6 +230,7 @@ public class AllBlocks {
.properties(p -> p.sound(SoundType.WOOD))
.transform(StressConfigDefaults.setNoImpact())
.blockstate(BlockStateGen.axisBlockProvider(false))
.onRegister(CreateRegistrate.blockModel(() -> BracketedKineticBlockModel::new))
.item(CogwheelBlockItem::new)
.build()
.register();
@ -470,6 +477,18 @@ public class AllBlocks {
.transform(ModelGen.customItemModel("gauge", "_", "item"))
.register();
public static final BlockEntry<BracketBlock> WOODEN_BRACKET = REGISTRATE.block("wooden_bracket", BracketBlock::new)
.blockstate(new BracketGenerator("wooden")::generate)
.item(BracketBlockItem::new)
.transform(BracketGenerator.itemModel("wooden"))
.register();
public static final BlockEntry<BracketBlock> METAL_BRACKET = REGISTRATE.block("metal_bracket", BracketBlock::new)
.blockstate(new BracketGenerator("metal")::generate)
.item(BracketBlockItem::new)
.transform(BracketGenerator.itemModel("metal"))
.register();
// Fluids
public static final BlockEntry<FluidPipeBlock> FLUID_PIPE = REGISTRATE.block("fluid_pipe", FluidPipeBlock::new)

View file

@ -2,17 +2,16 @@ package com.simibubi.create;
import java.util.function.Supplier;
import com.simibubi.create.content.contraptions.fluids.particle.FluidParticleData;
import com.simibubi.create.content.contraptions.particle.AirFlowParticleData;
import com.simibubi.create.content.contraptions.particle.AirParticleData;
import com.simibubi.create.content.contraptions.particle.CubeParticle;
import com.simibubi.create.content.contraptions.particle.CubeParticleData;
import com.simibubi.create.content.contraptions.particle.HeaterParticleData;
import com.simibubi.create.content.contraptions.particle.ICustomParticle;
import com.simibubi.create.content.contraptions.particle.ICustomParticleData;
import com.simibubi.create.content.contraptions.particle.RotationIndicatorParticleData;
import com.simibubi.create.foundation.utility.Lang;
import net.minecraft.client.Minecraft;
import net.minecraft.client.particle.IParticleFactory;
import net.minecraft.client.particle.ParticleManager;
import net.minecraft.particles.IParticleData;
import net.minecraft.particles.ParticleType;
@ -29,23 +28,20 @@ public enum AllParticleTypes {
AIR_FLOW(AirFlowParticleData::new),
AIR(AirParticleData::new),
HEATER_PARTICLE(HeaterParticleData::new),
CUBE(CubeParticleData::dummy, () -> CubeParticle.Factory::new)
CUBE(CubeParticleData::new),
FLUID_PARTICLE(FluidParticleData::new),
BASIN_FLUID(FluidParticleData::new),
FLUID_DRIP(FluidParticleData::new)
;
private ParticleEntry<?> entry;
<D extends IParticleData> AllParticleTypes(Supplier<? extends ICustomParticle<D>> typeFactory) {
<D extends IParticleData> AllParticleTypes(Supplier<? extends ICustomParticleData<D>> typeFactory) {
String asId = Lang.asId(this.name());
entry = new ParticleEntry<>(new ResourceLocation(Create.ID, asId), typeFactory);
}
<D extends IParticleData> AllParticleTypes(Supplier<? extends ICustomParticle<D>> typeFactory,
Supplier<Supplier<IParticleFactory<D>>> particleMetaFactory) {
String asId = Lang.asId(this.name());
entry = new ParticleEntry<>(new ResourceLocation(Create.ID, asId), typeFactory, particleMetaFactory);
}
public static void register(RegistryEvent.Register<ParticleType<?>> event) {
for (AllParticleTypes particle : values())
particle.entry.register(event.getRegistry());
@ -59,7 +55,7 @@ public enum AllParticleTypes {
}
public ParticleType<?> get() {
return entry.getType();
return entry.getOrCreateType();
}
public String parameter() {
@ -67,48 +63,32 @@ public enum AllParticleTypes {
}
private class ParticleEntry<D extends IParticleData> {
Supplier<? extends ICustomParticle<D>> typeFactory;
Supplier<Supplier<IParticleFactory<D>>> particleMetaFactory;
Supplier<? extends ICustomParticleData<D>> typeFactory;
ParticleType<D> type;
ResourceLocation id;
public ParticleEntry(ResourceLocation id, Supplier<? extends ICustomParticle<D>> typeFactory,
Supplier<Supplier<IParticleFactory<D>>> particleMetaFactory) {
public ParticleEntry(ResourceLocation id, Supplier<? extends ICustomParticleData<D>> typeFactory) {
this.id = id;
this.typeFactory = typeFactory;
this.particleMetaFactory = particleMetaFactory;
}
public ParticleEntry(ResourceLocation id, Supplier<? extends ICustomParticle<D>> typeFactory) {
this(id, typeFactory, null);
}
ParticleType<?> getType() {
makeType();
return type;
}
void register(IForgeRegistry<ParticleType<?>> registry) {
makeType();
registry.register(type);
registry.register(getOrCreateType());
}
void makeType() {
if (type == null) {
type = typeFactory.get()
.createType();
type.setRegistryName(id);
}
ParticleType<D> getOrCreateType() {
if (type != null)
return type;
type = typeFactory.get()
.createType();
type.setRegistryName(id);
return type;
}
@OnlyIn(Dist.CLIENT)
void registerFactory(ParticleManager particles) {
makeType();
if (particleMetaFactory == null)
particles.registerFactory(type, typeFactory.get()
.getFactory());
else
particles.registerFactory(type, particleMetaFactory.get().get());
typeFactory.get()
.register(getOrCreateType(), particles);
}
}

View file

@ -15,7 +15,7 @@ public class MixingCategory extends BasinCategory {
private final AnimatedMixer mixer = new AnimatedMixer();
private final AnimatedBlazeBurner heater = new AnimatedBlazeBurner();
private MixingType type;
MixingType type;
enum MixingType {
AUTO_SHAPELESS, MIXING, AUTO_BREWING;

View file

@ -5,6 +5,7 @@ import java.util.Optional;
import com.simibubi.create.AllRecipeTypes;
import com.simibubi.create.content.contraptions.components.press.MechanicalPressTileEntity;
import com.simibubi.create.content.contraptions.fluids.FluidFX;
import com.simibubi.create.content.contraptions.fluids.potion.PotionMixingRecipeManager;
import com.simibubi.create.content.contraptions.processing.BasinOperatingTileEntity;
import com.simibubi.create.content.contraptions.processing.BasinTileEntity;
@ -12,6 +13,8 @@ import com.simibubi.create.foundation.advancement.AllTriggers;
import com.simibubi.create.foundation.advancement.ITriggerable;
import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.item.SmartInventory;
import com.simibubi.create.foundation.tileEntity.behaviour.fluid.SmartFluidTankBehaviour;
import com.simibubi.create.foundation.tileEntity.behaviour.fluid.SmartFluidTankBehaviour.TankSegment;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.block.BlockState;
@ -20,6 +23,7 @@ import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.item.crafting.IRecipeSerializer;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.particles.IParticleData;
import net.minecraft.particles.ItemParticleData;
import net.minecraft.particles.ParticleTypes;
import net.minecraft.tileentity.TileEntityType;
@ -87,6 +91,9 @@ public class MechanicalMixerTileEntity extends BasinOperatingTileEntity {
running = compound.getBoolean("Running");
runningTicks = compound.getInt("Ticks");
super.fromTag(state, compound, clientPacket);
if (clientPacket && hasWorld())
getBasin().ifPresent(bte -> bte.setAreFluidsMoving(running && runningTicks <= 20));
}
@Override
@ -128,7 +135,6 @@ public class MechanicalMixerTileEntity extends BasinOperatingTileEntity {
if (runningTicks != 20)
runningTicks++;
}
}
public void renderParticles() {
@ -136,24 +142,38 @@ public class MechanicalMixerTileEntity extends BasinOperatingTileEntity {
if (!basin.isPresent() || world == null)
return;
SmartInventory inputs = basin.get()
.getInputInventory();
for (int slot = 0; slot < inputs.getSlots(); slot++) {
ItemStack stackInSlot = inputs.getStackInSlot(slot);
if (stackInSlot.isEmpty())
continue;
ItemParticleData data = new ItemParticleData(ParticleTypes.ITEM, stackInSlot);
float angle = world.rand.nextFloat() * 360;
Vector3d offset = new Vector3d(0, 0, 0.25f);
offset = VecHelper.rotate(offset, angle, Axis.Y);
Vector3d target = VecHelper.rotate(offset, getSpeed() > 0 ? 25 : -25, Axis.Y)
.add(0, .25f, 0);
Vector3d center = offset.add(VecHelper.getCenterOf(pos));
target = VecHelper.offsetRandomly(target.subtract(offset), world.rand, 1 / 128f);
world.addParticle(data, center.x, center.y - 2, center.z, target.x, target.y, target.z);
for (SmartInventory inv : basin.get()
.getInvs()) {
for (int slot = 0; slot < inv.getSlots(); slot++) {
ItemStack stackInSlot = inv.getStackInSlot(slot);
if (stackInSlot.isEmpty())
continue;
ItemParticleData data = new ItemParticleData(ParticleTypes.ITEM, stackInSlot);
spillParticle(data);
}
}
for (SmartFluidTankBehaviour behaviour : basin.get()
.getTanks()) {
if (behaviour == null)
continue;
for (TankSegment tankSegment : behaviour.getTanks()) {
if (tankSegment.isEmpty(0))
continue;
spillParticle(FluidFX.getFluidParticle(tankSegment.getRenderedFluid()));
}
}
}
protected void spillParticle(IParticleData data) {
float angle = world.rand.nextFloat() * 360;
Vector3d offset = new Vector3d(0, 0, 0.25f);
offset = VecHelper.rotate(offset, angle, Axis.Y);
Vector3d target = VecHelper.rotate(offset, getSpeed() > 0 ? 25 : -25, Axis.Y)
.add(0, .25f, 0);
Vector3d center = offset.add(VecHelper.getCenterOf(pos));
target = VecHelper.offsetRandomly(target.subtract(offset), world.rand, 1 / 128f);
world.addParticle(data, center.x, center.y - 1.75f, center.z, target.x, target.y, target.z);
}
@Override

View file

@ -2,6 +2,9 @@ package com.simibubi.create.content.contraptions.fluids;
import java.util.Random;
import com.simibubi.create.AllParticleTypes;
import com.simibubi.create.content.contraptions.fluids.particle.FluidParticleData;
import com.simibubi.create.foundation.fluid.FluidHelper;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.client.Minecraft;
@ -11,6 +14,7 @@ import net.minecraft.fluid.Fluids;
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.BlockPos;
import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.world.World;
@ -40,6 +44,56 @@ public class FluidFX {
}
public static IParticleData getFluidParticle(FluidStack fluid) {
return new FluidParticleData(AllParticleTypes.FLUID_PARTICLE.get(), fluid);
}
public static IParticleData getDrippingParticle(FluidStack fluid) {
IParticleData particle = null;
if (FluidHelper.isWater(fluid.getFluid()))
particle = ParticleTypes.DRIPPING_WATER;
if (FluidHelper.isLava(fluid.getFluid()))
particle = ParticleTypes.DRIPPING_LAVA;
if (particle == null)
particle = new FluidParticleData(AllParticleTypes.FLUID_DRIP.get(), fluid);
return particle;
}
public static void spawnRimParticles(World world, BlockPos pos, Direction side, int amount, IParticleData particle,
float rimRadius) {
Vector3d directionVec = Vector3d.of(side.getDirectionVec());
for (int i = 0; i < amount; i++) {
Vector3d vec = VecHelper.offsetRandomly(Vector3d.ZERO, r, 1)
.normalize();
vec = VecHelper.clampComponentWise(vec, rimRadius)
.mul(VecHelper.axisAlingedPlaneOf(directionVec))
.add(directionVec.scale(.45 + r.nextFloat() / 16f));
Vector3d 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);
}
}
public static void spawnPouringLiquid(World world, BlockPos pos, int amount, IParticleData particle,
float rimRadius, Vector3d directionVec, boolean inbound) {
for (int i = 0; i < amount; i++) {
Vector3d vec = VecHelper.offsetRandomly(Vector3d.ZERO, r, rimRadius * .75f);
vec = vec.mul(VecHelper.axisAlingedPlaneOf(directionVec))
.add(directionVec.scale(.5 + r.nextFloat() / 4f));
Vector3d m = vec.scale(1 / 4f);
Vector3d centerOf = VecHelper.getCenterOf(pos);
vec = vec.add(centerOf);
if (inbound) {
vec = vec.add(m);
m = centerOf.add(directionVec.scale(.5))
.subtract(vec)
.scale(1 / 16f);
}
world.addOptionalParticle(particle, vec.x, vec.y - 1 / 16f, vec.z, m.x, m.y, m.z);
}
}
private static void particle(IParticleData data, Vector3d pos, Vector3d motion) {
world().addParticle(data, pos.x, pos.y, pos.z, motion.x, motion.y, motion.z);
}

View file

@ -1,8 +1,9 @@
package com.simibubi.create.content.contraptions.fluids;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.fluids.pipes.EncasedPipeBlock;
import com.simibubi.create.content.contraptions.relays.elementary.BracketedTileEntityBehaviour;
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;
@ -10,7 +11,7 @@ import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockDisplayReader;
public class FluidPipeAttachmentBehaviour extends TileEntityBehaviour {
public class FluidPipeAttachmentBehaviour extends BracketedTileEntityBehaviour {
public static BehaviourType<FluidPipeAttachmentBehaviour> TYPE = new BehaviourType<>();
@ -36,6 +37,9 @@ public class FluidPipeAttachmentBehaviour extends TileEntityBehaviour {
FluidPipeBehaviour fluidPipeBehaviour = tileEntity.getBehaviour(FluidPipeBehaviour.TYPE);
if (fluidPipeBehaviour == null)
return false;
// BlockState bracket = getBracket();
// if (bracket != Blocks.AIR.getDefaultState() && bracket.get(BracketBlock.FACING) == direction)
// return false;
return fluidPipeBehaviour.isConnectedTo(state, direction);
}
@ -56,4 +60,14 @@ public class FluidPipeAttachmentBehaviour extends TileEntityBehaviour {
return TYPE;
}
@Override
public boolean canHaveBracket() {
BlockState blockState = tileEntity.getBlockState();
if (blockState.getBlock() instanceof PumpBlock)
return false;
if (blockState.getBlock() instanceof EncasedPipeBlock)
return false;
return true;
}
}

View file

@ -12,7 +12,6 @@ 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;
@ -31,9 +30,7 @@ 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;
@ -48,6 +45,10 @@ import net.minecraftforge.fml.DistExecutor;
public abstract class FluidPipeBehaviour extends TileEntityBehaviour {
public static BehaviourType<FluidPipeBehaviour> TYPE = new BehaviourType<>();
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();
// Direction -> (inboundflows{}, outwardflows{})
Map<Direction, Couple<PipeFlows>> allFlows;
@ -228,22 +229,17 @@ public abstract class FluidPipeBehaviour extends TileEntityBehaviour {
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();
public void spawnParticles() {
DistExecutor.runWhenOn(Dist.CLIENT, () -> this::spawnParticlesInner);
}
@OnlyIn(Dist.CLIENT)
private void spawnParticlesInner() {
if (!isRenderEntityWithinDistance())
if (!isRenderEntityWithinDistance(tileEntity.getPos()))
return;
if (fluid.isEmpty())
return;
@ -267,7 +263,7 @@ public abstract class FluidPipeBehaviour extends TileEntityBehaviour {
@OnlyIn(Dist.CLIENT)
private void spawnSplashOnRimInner(Direction face) {
if (!isRenderEntityWithinDistance())
if (!isRenderEntityWithinDistance(tileEntity.getPos()))
return;
if (fluid.isEmpty())
return;
@ -285,72 +281,36 @@ public abstract class FluidPipeBehaviour extends TileEntityBehaviour {
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;
IParticleData particle = FluidFX.getDrippingParticle(fluid);
float rimRadius = getRimRadius(state, side);
Vector3d directionVec = Vector3d.of(side.getDirectionVec());
for (int i = 0; i < amount; i++) {
Vector3d vec = VecHelper.offsetRandomly(Vector3d.ZERO, r, 1)
.normalize();
vec = VecHelper.clampComponentWise(vec, rimRadius)
.mul(VecHelper.axisAlingedPlaneOf(directionVec))
.add(directionVec.scale(.45 + r.nextFloat() / 16f));
Vector3d 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);
}
FluidFX.spawnRimParticles(world, pos, side, amount, particle, rimRadius);
}
@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());
IParticleData particle = FluidFX.getFluidParticle(fluid);
float rimRadius = getRimRadius(state, side);
Vector3d directionVec = Vector3d.of(side.getDirectionVec());
BlockPos pos = tileEntity.getPos();
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++) {
Vector3d vec = VecHelper.offsetRandomly(Vector3d.ZERO, r, rimRadius);
vec = vec.mul(VecHelper.axisAlingedPlaneOf(directionVec))
.add(directionVec.scale(.5 + r.nextFloat() / 4f));
Vector3d m = vec;
Vector3d 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);
}
FluidFX.spawnPouringLiquid(world, pos, amount, particle, rimRadius, directionVec, inbound);
});
}
@OnlyIn(Dist.CLIENT)
private boolean isRenderEntityWithinDistance() {
public static boolean isRenderEntityWithinDistance(BlockPos pos) {
Entity renderViewEntity = Minecraft.getInstance()
.getRenderViewEntity();
if (renderViewEntity == null)
return false;
Vector3d center = VecHelper.getCenterOf(tileEntity.getPos());
Vector3d center = VecHelper.getCenterOf(pos);
if (renderViewEntity.getPositionVec()
.distanceTo(center) > MAX_PARTICLE_RENDER_DISTANCE)
return false;

View file

@ -5,6 +5,8 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.annotation.Nullable;
import org.apache.commons.lang3.mutable.MutableObject;
import com.simibubi.create.AllBlocks;
@ -46,7 +48,7 @@ public class FluidPropagator {
return null;
if (otherBlock instanceof FlowingFluidBlock)
return null;
if (!isStraightPipe(state))
if (getStraightPipeAxis(state) == null)
return null;
for (Direction d : Iterate.directions) {
if (!pos.offset(d)
@ -162,12 +164,13 @@ public class FluidPropagator {
.isPresent();
}
public static boolean isStraightPipe(BlockState state) {
@Nullable
public static Axis getStraightPipeAxis(BlockState state) {
if (state.getBlock() instanceof AxisPipeBlock)
return true;
return state.get(AxisPipeBlock.AXIS);
if (!FluidPipeBlock.isPipe(state))
return false;
boolean axisFound = false;
return null;
Axis axisFound = null;
int connections = 0;
for (Axis axis : Iterate.axes) {
Direction d1 = Direction.getFacingFromAxis(AxisDirection.NEGATIVE, axis);
@ -179,12 +182,12 @@ public class FluidPropagator {
if (openAt2)
connections++;
if (openAt1 && openAt2)
if (axisFound)
return false;
if (axisFound != null)
return null;
else
axisFound = true;
axisFound = axis;
}
return axisFound && connections == 2;
return connections == 2 ? axisFound : null;
}
}

View file

@ -1,37 +1,64 @@
package com.simibubi.create.content.contraptions.fluids;
import java.util.List;
import javax.annotation.Nullable;
import com.simibubi.create.AllFluids;
import com.simibubi.create.content.contraptions.fluids.potion.PotionFluidHandler;
import com.simibubi.create.foundation.fluid.FluidHelper;
import com.simibubi.create.foundation.utility.BlockFace;
import com.simibubi.create.foundation.utility.BlockHelper;
import com.simibubi.create.foundation.utility.Iterate;
import net.minecraft.block.BlockState;
import net.minecraft.block.FlowingFluidBlock;
import net.minecraft.entity.LivingEntity;
import net.minecraft.fluid.Fluid;
import net.minecraft.fluid.FluidState;
import net.minecraft.fluid.Fluids;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.potion.Effect;
import net.minecraft.potion.EffectInstance;
import net.minecraft.potion.PotionUtils;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.tags.FluidTags;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvents;
import net.minecraft.util.math.AxisAlignedBB;
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.IFluidHandler.FluidAction;
import net.minecraftforge.fluids.capability.templates.FluidTank;
public class OpenEndedPipe {
World world;
BlockPos pos;
AxisAlignedBB aoe;
private OpenEndFluidHandler fluidHandler;
private BlockPos outputPos;
private boolean wasPulling;
private boolean stale;
private FluidStack cachedFluid;
private List<EffectInstance> cachedEffects;
public OpenEndedPipe(BlockFace face) {
fluidHandler = new OpenEndFluidHandler();
outputPos = face.getConnectedPos();
pos = face.getPos();
aoe = new AxisAlignedBB(outputPos).expand(0, -1, 0);
if (face.getFace() == Direction.DOWN)
aoe = aoe.expand(0, -1, 0);
}
public void tick(World world, boolean pulling) {
@ -59,7 +86,8 @@ public class OpenEndedPipe {
return;
if (waterlog) {
world.setBlockState(outputPos, state.with(BlockStateProperties.WATERLOGGED, false), 3);
world.getPendingFluidTicks().scheduleTick(outputPos, Fluids.WATER, 1);
world.getPendingFluidTicks()
.scheduleTick(outputPos, Fluids.WATER, 1);
return;
}
world.setBlockState(outputPos, fluidState.getBlockState()
@ -67,6 +95,20 @@ public class OpenEndedPipe {
return;
}
FluidStack fluid = fluidHandler.getFluid();
if (fluid.isEmpty())
return;
if (!FluidHelper.hasBlockState(fluid.getFluid())) {
fluidHandler.drain(fluid.getAmount() > 1 ? fluid.getAmount() - 1 : 1, FluidAction.EXECUTE);
if (fluidHandler.isEmpty())
updatePumpIfNecessary();
if (!fluid.getFluid()
.isEquivalentTo(AllFluids.POTION.get()))
return;
applyPotionEffects(world, fluid);
return;
}
Fluid providedFluid = fluidHandler.tryProvidingFluid();
if (providedFluid == null)
return;
@ -76,17 +118,55 @@ public class OpenEndedPipe {
}
if (fluidState.isSource())
return;
if (world.getDimension().isUltrawarm() && providedFluid.getFluid()
.isIn(FluidTags.WATER)) {
int i = outputPos.getX();
int j = outputPos.getY();
int k = outputPos.getZ();
world.playSound(null, i, j, k, SoundEvents.BLOCK_FIRE_EXTINGUISH, SoundCategory.BLOCKS, 0.5F,
2.6F + (world.rand.nextFloat() - world.rand.nextFloat()) * 0.8F);
return;
}
if (waterlog) {
if (providedFluid.getFluid() != Fluids.WATER)
return;
world.setBlockState(outputPos, state.with(BlockStateProperties.WATERLOGGED, true), 3);
world.getPendingFluidTicks().scheduleTick(outputPos, Fluids.WATER, 1);
world.getPendingFluidTicks()
.scheduleTick(outputPos, Fluids.WATER, 1);
return;
}
world.setBlockState(outputPos, providedFluid.getDefaultState()
.getBlockState(), 3);
}
private void applyPotionEffects(World world, FluidStack fluid) {
if (cachedFluid == null || cachedEffects == null || !fluid.isFluidEqual(cachedFluid)) {
FluidStack copy = fluid.copy();
copy.setAmount(250);
ItemStack bottle = PotionFluidHandler.fillBottle(new ItemStack(Items.GLASS_BOTTLE), fluid);
cachedEffects = PotionUtils.getEffectsFromStack(bottle);
}
if (cachedEffects.isEmpty())
return;
List<LivingEntity> list =
this.world.getEntitiesWithinAABB(LivingEntity.class, aoe, LivingEntity::canBeHitWithPotion);
for (LivingEntity livingentity : list) {
for (EffectInstance effectinstance : cachedEffects) {
Effect effect = effectinstance.getPotion();
if (effect.isInstant()) {
effect.affectEntity(null, null, livingentity, effectinstance.getAmplifier(), 0.5D);
continue;
}
livingentity.addPotionEffect(new EffectInstance(effectinstance));
}
}
}
public LazyOptional<IFluidHandler> getCapability() {
return LazyOptional.of(() -> fluidHandler);
}
@ -114,6 +194,16 @@ public class OpenEndedPipe {
return stale;
}
private void updatePumpIfNecessary() {
if (world == null)
return;
if (!PumpBlock.isPump(world.getBlockState(pos)))
return;
TileEntity tileEntity = world.getTileEntity(pos);
if (tileEntity instanceof PumpTileEntity)
((PumpTileEntity) tileEntity).sendData();
}
private class OpenEndFluidHandler extends FluidTank {
public OpenEndFluidHandler() {
@ -129,6 +219,8 @@ public class OpenEndedPipe {
return 0;
if (resource.isEmpty())
return 0;
FluidStack prevFluid = getFluid();
BlockState state = world.getBlockState(outputPos);
FluidState fluidState = state.getFluidState();
if (!fluidState.isEmpty() && fluidState.getFluid() != resource.getFluid()) {
@ -145,7 +237,30 @@ public class OpenEndedPipe {
// 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);
int fill = super.fill(insertable, action);
if (!getFluid().isFluidEqual(prevFluid))
updatePumpIfNecessary();
return fill;
}
@Override
public FluidStack drain(FluidStack resource, FluidAction action) {
boolean wasEmpty = isEmpty();
FluidStack drain = super.drain(resource, action);
if (action.execute() && !wasEmpty && isEmpty())
updatePumpIfNecessary();
return drain;
}
@Override
public FluidStack drain(int maxDrain, FluidAction action) {
boolean wasEmpty = isEmpty();
FluidStack drain = super.drain(maxDrain, action);
if (action.execute() && !wasEmpty && isEmpty())
updatePumpIfNecessary();
return drain;
}
public boolean tryCollectFluid(Fluid fluid) {
@ -153,6 +268,7 @@ public class OpenEndedPipe {
if (super.fill(new FluidStack(fluid, 1000),
simulate ? FluidAction.SIMULATE : FluidAction.EXECUTE) != 1000)
return false;
updatePumpIfNecessary();
return true;
}
@ -162,11 +278,15 @@ public class OpenEndedPipe {
for (boolean simulate : Iterate.trueAndFalse)
if (drain(1000, simulate ? FluidAction.SIMULATE : FluidAction.EXECUTE).getAmount() != 1000)
return null;
updatePumpIfNecessary();
return fluid;
}
public void clear() {
boolean wasEmpty = isEmpty();
setFluid(FluidStack.EMPTY);
if (!wasEmpty)
updatePumpIfNecessary();
}
}

View file

@ -13,6 +13,7 @@ import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
import com.simibubi.create.foundation.utility.Iterate;
import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.model.BakedQuad;
import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.util.Direction;
@ -35,10 +36,14 @@ public class PipeAttachmentModel extends WrappedBakedModel {
PipeModelData data = new PipeModelData();
FluidPipeAttachmentBehaviour attachmentBehaviour =
TileEntityBehaviour.get(world, pos, FluidPipeAttachmentBehaviour.TYPE);
if (attachmentBehaviour != null)
if (attachmentBehaviour != null) {
for (Direction d : Iterate.directions)
data.putRim(d, attachmentBehaviour.getAttachment(world, pos, state, d));
data.putBracket(attachmentBehaviour.getBracket());
}
data.setEncased(FluidPipeBlock.shouldDrawCasing(world, pos, state));
return new ModelDataMap.Builder().withInitial(PIPE_PROPERTY, data)
.build();
}
@ -67,17 +72,31 @@ public class PipeAttachmentModel extends WrappedBakedModel {
if (pipeData.isEncased())
quads.addAll(AllBlockPartials.FLUID_PIPE_CASING.get()
.getQuads(state, side, rand, data));
IBakedModel bracket = pipeData.getBracket();
if (bracket != null)
quads.addAll(bracket.getQuads(state, side, rand, data));
}
private class PipeModelData {
AttachmentTypes[] rims;
boolean encased;
IBakedModel bracket;
public PipeModelData() {
rims = new AttachmentTypes[6];
Arrays.fill(rims, AttachmentTypes.NONE);
}
public void putBracket(BlockState state) {
this.bracket = Minecraft.getInstance()
.getBlockRendererDispatcher()
.getModelForState(state);
}
public IBakedModel getBracket() {
return bracket;
}
public void putRim(Direction face, AttachmentTypes rim) {
rims[face.getIndex()] = rim;
}

View file

@ -7,6 +7,8 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
import org.apache.commons.lang3.mutable.MutableBoolean;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
@ -22,14 +24,19 @@ 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.particles.IParticleData;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.world.IBlockDisplayReader;
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.fluids.capability.IFluidHandler;
import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction;
import net.minecraftforge.fml.DistExecutor;
public class PumpTileEntity extends KineticTileEntity {
@ -70,6 +77,7 @@ public class PumpTileEntity extends KineticTileEntity {
if (world.isRemote) {
if (speed == 0)
return;
spawnParticles();
arrowDirection.chase(speed >= 0 ? 1 : -1, .5f, Chaser.EXP);
arrowDirection.tickChaser();
return;
@ -279,6 +287,14 @@ public class PumpTileEntity extends KineticTileEntity {
return isFront;
}
@Nullable
protected Direction getFront() {
BlockState blockState = getBlockState();
if (!(blockState.getBlock() instanceof PumpBlock))
return null;
return blockState.get(PumpBlock.FACING);
}
protected void updatePipeNetwork(boolean front) {
if (networks != null)
networks.get(front)
@ -301,6 +317,44 @@ public class PumpTileEntity extends KineticTileEntity {
return front == reversed;
}
public void spawnParticles() {
DistExecutor.runWhenOn(Dist.CLIENT, () -> this::spawnParticlesInner);
}
@OnlyIn(Dist.CLIENT)
private void spawnParticlesInner() {
if (!FluidPipeBehaviour.isRenderEntityWithinDistance(pos))
return;
for (boolean front : Iterate.trueAndFalse) {
Direction side = getFront();
if (side == null)
return;
if (!front)
side = side.getOpposite();
if (!FluidPropagator.isOpenEnd(world, pos, side))
continue;
BlockFace key = new BlockFace(pos, side);
Map<BlockFace, OpenEndedPipe> map = openEnds.get(front);
if (map.containsKey(key)) {
FluidStack fluidStack = map.get(key)
.getCapability()
.map(fh -> fh.getFluidInTank(0))
.orElse(FluidStack.EMPTY);
if (!fluidStack.isEmpty())
spawnPouringLiquid(fluidStack, side, 1);
}
}
}
@OnlyIn(Dist.CLIENT)
private void spawnPouringLiquid(FluidStack fluid, Direction side, int amount) {
IParticleData particle = FluidFX.getFluidParticle(fluid);
float rimRadius = 1 / 4f + 1 / 64f;
boolean inbound = isPullingOnSide(getFront() == side);
Vector3d directionVec = Vector3d.of(side.getDirectionVec());
FluidFX.spawnPouringLiquid(world, pos, amount, particle, rimRadius, directionVec, inbound);
}
public Map<BlockFace, OpenEndedPipe> getOpenEnds(Direction side) {
return openEnds.get(isFront(side));
}

View file

@ -249,7 +249,7 @@ public class FluidDrainingBehaviour extends FluidManipulationBehaviour {
World world = getWorld();
int maxBlocks = maxBlocks();
if (visited.size() > maxBlocks) {
if (visited.size() > maxBlocks && maxBlocks != -1) {
infinite = true;
// Find first block with valid fluid
while (true) {
@ -280,10 +280,9 @@ public class FluidDrainingBehaviour extends FluidManipulationBehaviour {
search(fluid, validationFrontier, validationVisited, (e, d) -> newValidationSet.add(e), false);
int maxBlocks = maxBlocks();
if (validationVisited.size() > maxBlocks) {
if (!infinite) {
if (validationVisited.size() > maxBlocks && maxBlocks != -1) {
if (!infinite)
reset();
}
validationFrontier.clear();
setLongValidationTimer();
return;

View file

@ -12,16 +12,26 @@ import com.simibubi.create.foundation.utility.Iterate;
import it.unimi.dsi.fastutil.PriorityQueue;
import it.unimi.dsi.fastutil.objects.ObjectHeapPriorityQueue;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.DoorBlock;
import net.minecraft.block.FlowingFluidBlock;
import net.minecraft.block.material.Material;
import net.minecraft.fluid.Fluid;
import net.minecraft.fluid.FluidState;
import net.minecraft.fluid.Fluids;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.tags.BlockTags;
import net.minecraft.tags.FluidTags;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvents;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MutableBoundingBox;
import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.ITickList;
import net.minecraft.world.NextTickListEntry;
import net.minecraft.world.World;
@ -60,7 +70,7 @@ public class FluidFillingBehaviour extends FluidManipulationBehaviour {
(p, d) -> infinityCheckFrontier.add(new BlockPosEntry(p, d)), true);
int maxBlocks = maxBlocks();
if (infinityCheckVisited.size() > maxBlocks) {
if (infinityCheckVisited.size() > maxBlocks && maxBlocks != -1) {
if (!infinite) {
reset();
infinite = true;
@ -111,16 +121,25 @@ public class FluidFillingBehaviour extends FluidManipulationBehaviour {
int maxRange = maxRange();
int maxRangeSq = maxRange * maxRange;
int maxBlocks = maxBlocks();
boolean evaporate = world.getDimension()
.isUltrawarm() && fluid.isIn(FluidTags.WATER);
if (infinite) {
if (infinite || evaporate) {
FluidState fluidState = world.getFluidState(rootPos);
boolean equivalentTo = fluidState.getFluid()
.isEquivalentTo(fluid);
if (!equivalentTo)
if (!equivalentTo && !evaporate)
return false;
if (simulate)
return true;
playEffect(world, BlockPos.ZERO, fluid, false);
playEffect(world, null, fluid, false);
if (evaporate) {
int i = root.getX();
int j = root.getY();
int k = root.getZ();
world.playSound(null, i, j, k, SoundEvents.BLOCK_FIRE_EXTINGUISH, SoundCategory.BLOCKS, 0.5F,
2.6F + (world.rand.nextFloat() - world.rand.nextFloat()) * 0.8F);
}
return true;
}
@ -137,7 +156,7 @@ public class FluidFillingBehaviour extends FluidManipulationBehaviour {
if (!simulate)
visited.add(currentPos);
if (visited.size() >= maxBlocks) {
if (visited.size() >= maxBlocks && maxBlocks != -1) {
infinite = true;
visited.clear();
queue.clear();
@ -154,9 +173,10 @@ public class FluidFillingBehaviour extends FluidManipulationBehaviour {
BlockState blockState = world.getBlockState(currentPos);
if (blockState.contains(BlockStateProperties.WATERLOGGED) && fluid.isEquivalentTo(Fluids.WATER)) {
world.setBlockState(currentPos, blockState.with(BlockStateProperties.WATERLOGGED, true),
2 | 16);
world.setBlockState(currentPos,
updatePostWaterlogging(blockState.with(BlockStateProperties.WATERLOGGED, true)), 2 | 16);
} else {
replaceBlock(world, currentPos, blockState);
world.setBlockState(currentPos, fluid.getDefaultState()
.getBlockState(), 2 | 16);
}
@ -237,8 +257,36 @@ public class FluidFillingBehaviour extends FluidManipulationBehaviour {
.isEmpty())
return toFill.isEquivalentTo(fluidState.getFluid()) ? SpaceType.FILLED : SpaceType.BLOCKING;
return blockState.getMaterial()
.isReplaceable() ? SpaceType.FILLABLE : SpaceType.BLOCKING;
return canBeReplacedByFluid(world, pos, blockState) ? SpaceType.FILLABLE : SpaceType.BLOCKING;
}
protected void replaceBlock(World world, BlockPos pos, BlockState state) {
TileEntity tileentity = state.getBlock()
.hasTileEntity(state) ? world.getTileEntity(pos) : null;
Block.spawnDrops(state, world, pos, tileentity);
}
// From FlowingFluidBlock#isBlocked
protected boolean canBeReplacedByFluid(IBlockReader world, BlockPos pos, BlockState state) {
Block block = state.getBlock();
if (!(block instanceof DoorBlock) && !block.isIn(BlockTags.SIGNS) && block != Blocks.LADDER
&& block != Blocks.SUGAR_CANE && block != Blocks.BUBBLE_COLUMN) {
Material material = state.getMaterial();
if (material != Material.PORTAL && material != Material.STRUCTURE_VOID && material != Material.OCEAN_PLANT
&& material != Material.SEA_GRASS) {
return !material.blocksMovement();
} else {
return false;
}
} else {
return false;
}
}
protected BlockState updatePostWaterlogging(BlockState state) {
if (state.contains(BlockStateProperties.LIT))
state = state.with(BlockStateProperties.LIT, false);
return state;
}
@Override

View file

@ -6,6 +6,7 @@ import java.util.List;
import java.util.Set;
import java.util.function.BiConsumer;
import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.fluid.FluidHelper;
import com.simibubi.create.foundation.networking.AllPackets;
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
@ -76,11 +77,11 @@ public abstract class FluidManipulationBehaviour extends TileEntityBehaviour {
}
protected int maxRange() {
return 128;
return AllConfigs.SERVER.fluids.hosePulleyRange.get();
}
protected int maxBlocks() {
return 10000;
return AllConfigs.SERVER.fluids.hosePulleyBlockThreshold.get();
}
public void reset() {
@ -135,7 +136,8 @@ public abstract class FluidManipulationBehaviour extends TileEntityBehaviour {
int maxRangeSq = maxRange * maxRange;
int i;
for (i = 0; i < searchedPerTick && !frontier.isEmpty() && visited.size() <= maxBlocks; i++) {
for (i = 0; i < searchedPerTick && !frontier.isEmpty()
&& (visited.size() <= maxBlocks || maxBlocks == -1); i++) {
BlockPosEntry entry = frontier.remove(0);
BlockPos currentPos = entry.pos;
if (visited.contains(currentPos))
@ -178,7 +180,7 @@ public abstract class FluidManipulationBehaviour extends TileEntityBehaviour {
}
protected void playEffect(World world, BlockPos pos, Fluid fluid, boolean fillSound) {
BlockPos splooshPos = infinite ? tileEntity.getPos() : pos;
BlockPos splooshPos = pos == null ? tileEntity.getPos() : pos;
SoundEvent soundevent = fillSound ? fluid.getAttributes()
.getFillSound()

View file

@ -4,6 +4,7 @@ import java.util.function.Supplier;
import javax.annotation.Nullable;
import com.simibubi.create.foundation.fluid.FluidHelper;
import com.simibubi.create.foundation.fluid.SmartFluidTank;
import net.minecraft.util.math.BlockPos;
@ -18,6 +19,8 @@ public class HosePulleyFluidHandler implements IFluidHandler {
public int fill(FluidStack resource, FluidAction action) {
if (!internalTank.isEmpty() && !resource.isFluidEqual(internalTank.getFluid()))
return 0;
if (resource.isEmpty() || !FluidHelper.hasBlockState(resource.getFluid()))
return 0;
int diff = resource.getAmount();
int totalAmountAfterFill = diff + internalTank.getFluidAmount();

View file

@ -2,6 +2,7 @@ package com.simibubi.create.content.contraptions.fluids.actors;
import com.simibubi.create.AllShapes;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.content.contraptions.wrench.IWrenchable;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
@ -11,7 +12,7 @@ import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.world.IBlockReader;
public class SpoutBlock extends Block {
public class SpoutBlock extends Block implements IWrenchable {
public SpoutBlock(Properties p_i48440_1_) {
super(p_i48440_1_);

View file

@ -0,0 +1,100 @@
package com.simibubi.create.content.contraptions.fluids.particle;
import com.mojang.blaze3d.vertex.IVertexBuilder;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.processing.BasinTileEntity;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.client.renderer.ActiveRenderInfo;
import net.minecraft.client.renderer.Quaternion;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.fluids.FluidStack;
public class BasinFluidParticle extends FluidStackParticle {
BlockPos basinPos;
Vec3d targetPos;
Vec3d centerOfBasin;
float yOffset;
public BasinFluidParticle(World world, FluidStack fluid, double x, double y, double z, double vx, double vy,
double vz) {
super(world, fluid, x, y, z, vx, vy, vz);
particleGravity = 0;
motionX = 0;
motionY = 0;
motionZ = 0;
yOffset = world.rand.nextFloat() * 1 / 32f;
posY += yOffset;
particleScale = 0;
maxAge = 60;
Vec3d currentPos = new Vec3d(posX, posY, posZ);
basinPos = new BlockPos(currentPos);
centerOfBasin = VecHelper.getCenterOf(basinPos);
if (vx != 0) {
maxAge = 20;
Vec3d centerOf = VecHelper.getCenterOf(basinPos);
Vec3d diff = currentPos.subtract(centerOf)
.mul(1, 0, 1)
.normalize()
.scale(.375);
targetPos = centerOf.add(diff);
prevPosX = posX = centerOfBasin.x;
prevPosZ = posZ = centerOfBasin.z;
}
}
@Override
public void tick() {
super.tick();
particleScale = targetPos != null ? Math.max(1 / 32f, ((1f * age) / maxAge) / 8)
: 1 / 8f * (1 - ((Math.abs(age - (maxAge / 2)) / (1f * maxAge))));
if (age % 2 == 0) {
if (!AllBlocks.BASIN.has(world.getBlockState(basinPos))) {
setExpired();
return;
}
TileEntity tileEntity = world.getTileEntity(basinPos);
if (tileEntity instanceof BasinTileEntity) {
float totalUnits = ((BasinTileEntity) tileEntity).getTotalFluidUnits();
if (totalUnits < 1)
totalUnits = 0;
float fluidLevel = MathHelper.clamp(totalUnits / 2000, 0, 1);
posY = 2 / 16f + basinPos.getY() + 12 / 16f * fluidLevel + yOffset;
}
}
if (targetPos != null) {
float progess = (1f * age) / maxAge;
Vec3d currentPos = centerOfBasin.add(targetPos.subtract(centerOfBasin)
.scale(progess));
posX = currentPos.x;
posZ = currentPos.z;
}
}
@Override
public void buildGeometry(IVertexBuilder vb, ActiveRenderInfo info, float pt) {
Quaternion rotation = info.getRotation();
Quaternion prevRotation = new Quaternion(rotation);
rotation.set(1, 0, 0, 1);
rotation.normalize();
super.buildGeometry(vb, info, pt);
rotation.set(0, 0, 0, 1);
rotation.multiply(prevRotation);
}
@Override
protected boolean canEvaporate() {
return false;
}
}

View file

@ -0,0 +1,72 @@
package com.simibubi.create.content.contraptions.fluids.particle;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.simibubi.create.content.contraptions.particle.ICustomParticleData;
import net.minecraft.client.particle.IParticleFactory;
import net.minecraft.fluid.Fluids;
import net.minecraft.network.PacketBuffer;
import net.minecraft.particles.IParticleData;
import net.minecraft.particles.ParticleType;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.registries.ForgeRegistries;
public class FluidParticleData implements IParticleData, ICustomParticleData<FluidParticleData> {
private ParticleType<FluidParticleData> type;
private FluidStack fluid;
public FluidParticleData() {}
@SuppressWarnings("unchecked")
public FluidParticleData(ParticleType<?> type, FluidStack fluid) {
this.type = (ParticleType<FluidParticleData>) type;
this.fluid = fluid;
}
@Override
@OnlyIn(Dist.CLIENT)
public IParticleFactory<FluidParticleData> getFactory() {
return (data, world, x, y, z, vx, vy, vz) -> FluidStackParticle.create(data.type, world, data.fluid, x, y, z,
vx, vy, vz);
}
@Override
public ParticleType<?> getType() {
return type;
}
@Override
public void write(PacketBuffer buffer) {
buffer.writeFluidStack(fluid);
}
@Override
public String getParameters() {
return ForgeRegistries.PARTICLE_TYPES.getKey(type) + " " + fluid.getFluid()
.getRegistryName();
}
public static final IParticleData.IDeserializer<FluidParticleData> DESERIALIZER =
new IParticleData.IDeserializer<FluidParticleData>() {
// TODO Fluid particles on command
public FluidParticleData deserialize(ParticleType<FluidParticleData> particleTypeIn, StringReader reader)
throws CommandSyntaxException {
return new FluidParticleData(particleTypeIn, new FluidStack(Fluids.WATER, 1));
}
public FluidParticleData read(ParticleType<FluidParticleData> particleTypeIn, PacketBuffer buffer) {
return new FluidParticleData(particleTypeIn, buffer.readFluidStack());
}
};
@Override
public IDeserializer<FluidParticleData> getDeserializer() {
return DESERIALIZER;
}
}

View file

@ -0,0 +1,116 @@
package com.simibubi.create.content.contraptions.fluids.particle;
import com.simibubi.create.AllParticleTypes;
import com.simibubi.create.content.contraptions.fluids.potion.PotionFluid;
import com.simibubi.create.foundation.utility.ColorHelper;
import net.minecraft.client.Minecraft;
import net.minecraft.client.particle.IParticleRenderType;
import net.minecraft.client.particle.SpriteTexturedParticle;
import net.minecraft.inventory.container.PlayerContainer;
import net.minecraft.particles.ParticleType;
import net.minecraft.particles.ParticleTypes;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.fluids.FluidStack;
public class FluidStackParticle extends SpriteTexturedParticle {
private final float field_217587_G;
private final float field_217588_H;
private FluidStack fluid;
public static FluidStackParticle create(ParticleType<FluidParticleData> type, World world, FluidStack fluid, double x,
double y, double z, double vx, double vy, double vz) {
if (type == AllParticleTypes.BASIN_FLUID.get())
return new BasinFluidParticle(world, fluid, x, y, z, vx, vy, vz);
return new FluidStackParticle(world, fluid, x, y, z, vx, vy, vz);
}
public FluidStackParticle(World world, FluidStack fluid, double x, double y, double z, double vx, double vy,
double vz) {
super(world, x, y, z, vx, vy, vz);
this.fluid = fluid;
this.setSprite(Minecraft.getInstance()
.getSpriteAtlas(PlayerContainer.BLOCK_ATLAS_TEXTURE)
.apply(fluid.getFluid()
.getAttributes()
.getStillTexture()));
this.particleGravity = 1.0F;
this.particleRed = 0.8F;
this.particleGreen = 0.8F;
this.particleBlue = 0.8F;
this.multiplyColor(fluid.getFluid()
.getAttributes()
.getColor(fluid));
this.motionX = vx;
this.motionY = vy;
this.motionZ = vz;
this.particleScale /= 2.0F;
this.field_217587_G = this.rand.nextFloat() * 3.0F;
this.field_217588_H = this.rand.nextFloat() * 3.0F;
}
@Override
protected int getBrightnessForRender(float p_189214_1_) {
int brightnessForRender = super.getBrightnessForRender(p_189214_1_);
int skyLight = brightnessForRender >> 20;
int blockLight = (brightnessForRender >> 4) & 0xf;
blockLight = Math.max(blockLight, fluid.getFluid()
.getAttributes()
.getLuminosity(fluid));
return (skyLight << 20) | (blockLight << 4);
}
protected void multiplyColor(int color) {
this.particleRed *= (float) (color >> 16 & 255) / 255.0F;
this.particleGreen *= (float) (color >> 8 & 255) / 255.0F;
this.particleBlue *= (float) (color & 255) / 255.0F;
}
protected float getMinU() {
return this.sprite.getInterpolatedU((double) ((this.field_217587_G + 1.0F) / 4.0F * 16.0F));
}
protected float getMaxU() {
return this.sprite.getInterpolatedU((double) (this.field_217587_G / 4.0F * 16.0F));
}
protected float getMinV() {
return this.sprite.getInterpolatedV((double) (this.field_217588_H / 4.0F * 16.0F));
}
protected float getMaxV() {
return this.sprite.getInterpolatedV((double) ((this.field_217588_H + 1.0F) / 4.0F * 16.0F));
}
@Override
public void tick() {
super.tick();
if (!canEvaporate())
return;
if (onGround)
setExpired();
if (!isExpired)
return;
if (!onGround && world.rand.nextFloat() < 1 / 8f)
return;
Vec3d rgb = ColorHelper.getRGB(fluid.getFluid()
.getAttributes()
.getColor(fluid));
world.addParticle(ParticleTypes.ENTITY_EFFECT, posX, posY, posZ, rgb.x, rgb.y, rgb.z);
}
protected boolean canEvaporate() {
return fluid.getFluid() instanceof PotionFluid;
}
@Override
public IParticleRenderType getRenderType() {
return IParticleRenderType.TERRAIN_SHEET;
}
}

View file

@ -1,15 +1,19 @@
package com.simibubi.create.content.contraptions.fluids.pipes;
import java.util.Map;
import java.util.Optional;
import java.util.Random;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllShapes;
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.content.contraptions.wrench.IWrenchableWithBracket;
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.RotatedPillarBlock;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
@ -28,7 +32,7 @@ import net.minecraft.world.TickPriority;
import net.minecraft.world.World;
import net.minecraft.world.server.ServerWorld;
public class AxisPipeBlock extends RotatedPillarBlock implements IWrenchable, IAxisPipe {
public class AxisPipeBlock extends RotatedPillarBlock implements IWrenchableWithBracket, IAxisPipe {
public AxisPipeBlock(Properties p_i48339_1_) {
super(p_i48339_1_);
@ -39,6 +43,8 @@ public class AxisPipeBlock extends RotatedPillarBlock implements IWrenchable, IA
boolean blockTypeChanged = state.getBlock() != newState.getBlock();
if (blockTypeChanged && !world.isRemote)
FluidPropagator.propagateChangedPipe(world, pos, state);
if (state != newState && !isMoving)
removeBracket(world, pos).ifPresent(stack -> Block.spawnAsEntity(world, pos, stack));
if (state.hasTileEntity() && (blockTypeChanged || !newState.hasTileEntity()))
world.removeTileEntity(pos);
}
@ -100,4 +106,16 @@ public class AxisPipeBlock extends RotatedPillarBlock implements IWrenchable, IA
return state.get(AXIS);
}
@Override
public Optional<ItemStack> removeBracket(IBlockReader world, BlockPos pos) {
FluidPipeAttachmentBehaviour behaviour = TileEntityBehaviour.get(world, pos, FluidPipeAttachmentBehaviour.TYPE);
if (behaviour == null)
return Optional.empty();
BlockState bracket = behaviour.getBracket();
behaviour.removeBracket();
if (bracket == Blocks.AIR.getDefaultState())
return Optional.empty();
return Optional.of(new ItemStack(bracket.getBlock()));
}
}

View file

@ -0,0 +1,66 @@
package com.simibubi.create.content.contraptions.fluids.pipes;
import java.util.Optional;
import com.simibubi.create.content.contraptions.base.DirectionalAxisKineticBlock;
import com.simibubi.create.content.contraptions.base.RotatedPillarKineticBlock;
import com.simibubi.create.content.contraptions.fluids.FluidPropagator;
import com.simibubi.create.content.contraptions.relays.elementary.CogWheelBlock;
import com.simibubi.create.content.contraptions.relays.elementary.ShaftBlock;
import com.simibubi.create.foundation.block.ProperDirectionalBlock;
import com.simibubi.create.foundation.utility.Lang;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.state.BooleanProperty;
import net.minecraft.state.EnumProperty;
import net.minecraft.state.StateContainer.Builder;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.IStringSerializable;
public class BracketBlock extends ProperDirectionalBlock {
public static final BooleanProperty AXIS_ALONG_FIRST_COORDINATE =
DirectionalAxisKineticBlock.AXIS_ALONG_FIRST_COORDINATE;
public static final EnumProperty<BracketType> TYPE = EnumProperty.create("type", BracketType.class);
public static enum BracketType implements IStringSerializable {
PIPE, COG, SHAFT;
@Override
public String getName() {
return Lang.asId(name());
}
}
@Override
protected void fillStateContainer(Builder<Block, BlockState> builder) {
super.fillStateContainer(builder.add(AXIS_ALONG_FIRST_COORDINATE)
.add(TYPE));
}
public BracketBlock(Properties p_i48415_1_) {
super(p_i48415_1_);
}
public Optional<BlockState> getSuitableBracket(BlockState blockState, Direction direction) {
if (blockState.getBlock() instanceof ShaftBlock)
return getSuitableBracket(blockState.get(RotatedPillarKineticBlock.AXIS), direction,
blockState.getBlock() instanceof CogWheelBlock ? BracketType.COG : BracketType.SHAFT);
return getSuitableBracket(FluidPropagator.getStraightPipeAxis(blockState), direction, BracketType.PIPE);
}
private Optional<BlockState> getSuitableBracket(Axis targetBlockAxis, Direction direction, BracketType type) {
Axis axis = direction.getAxis();
if (targetBlockAxis == null || targetBlockAxis == axis)
return Optional.empty();
boolean alongFirst = axis != Axis.Z ? targetBlockAxis == Axis.Z : targetBlockAxis == Axis.Y;
return Optional.of(getDefaultState().with(TYPE, type)
.with(FACING, direction)
.with(AXIS_ALONG_FIRST_COORDINATE, !alongFirst));
}
}

View file

@ -0,0 +1,73 @@
package com.simibubi.create.content.contraptions.fluids.pipes;
import java.util.Optional;
import com.simibubi.create.content.contraptions.fluids.FluidPipeAttachmentBehaviour;
import com.simibubi.create.content.contraptions.relays.elementary.BracketedTileEntityBehaviour;
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUseContext;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
public class BracketBlockItem extends BlockItem {
public BracketBlockItem(Block p_i48527_1_, Properties p_i48527_2_) {
super(p_i48527_1_, p_i48527_2_);
}
@Override
public ActionResultType onItemUse(ItemUseContext context) {
World world = context.getWorld();
BlockPos pos = context.getPos();
BlockState state = world.getBlockState(pos);
BracketBlock bracketBlock = getBracketBlock();
PlayerEntity player = context.getPlayer();
BracketedTileEntityBehaviour behaviour = TileEntityBehaviour.get(world, pos, FluidPipeAttachmentBehaviour.TYPE);
if (behaviour == null)
behaviour = TileEntityBehaviour.get(world, pos, BracketedTileEntityBehaviour.TYPE);
if (behaviour != null && behaviour.canHaveBracket()) {
if (world.isRemote)
return ActionResultType.SUCCESS;
Optional<BlockState> suitableBracket = bracketBlock.getSuitableBracket(state, context.getFace());
if (!suitableBracket.isPresent() && player != null)
suitableBracket =
bracketBlock.getSuitableBracket(state, Direction.getFacingDirections(player)[0].getOpposite());
if (!suitableBracket.isPresent())
return ActionResultType.SUCCESS;
BlockState bracket = behaviour.getBracket();
behaviour.applyBracket(suitableBracket.get());
if (player == null || !player.isCreative()) {
context.getItem()
.shrink(1);
if (bracket != Blocks.AIR.getDefaultState()) {
ItemStack returnedStack = new ItemStack(bracket.getBlock());
if (player == null)
Block.spawnAsEntity(world, pos, returnedStack);
else
player.inventory.placeItemBackInInventory(world, returnedStack);
}
}
return ActionResultType.SUCCESS;
}
return ActionResultType.FAIL;
}
private BracketBlock getBracketBlock() {
return (BracketBlock) getBlock();
}
}

View file

@ -0,0 +1,52 @@
package com.simibubi.create.content.contraptions.fluids.pipes;
import com.simibubi.create.foundation.data.DirectionalAxisBlockStateGen;
import com.tterrag.registrate.builders.ItemBuilder;
import com.tterrag.registrate.providers.DataGenContext;
import com.tterrag.registrate.providers.RegistrateBlockstateProvider;
import com.tterrag.registrate.util.nullness.NonNullFunction;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.item.BlockItem;
import net.minecraftforge.client.model.generators.ModelFile;
public class BracketGenerator extends DirectionalAxisBlockStateGen {
private String material;
public BracketGenerator(String material) {
this.material = material;
}
@Override
public <T extends Block> String getModelPrefix(DataGenContext<Block, T> ctx, RegistrateBlockstateProvider prov,
BlockState state) {
return "";
}
@Override
public <T extends Block> ModelFile getModel(DataGenContext<Block, T> ctx, RegistrateBlockstateProvider prov,
BlockState state) {
String type = state.get(BracketBlock.TYPE)
.getName();
boolean vertical = state.get(BracketBlock.FACING)
.getAxis()
.isVertical();
String path = "block/bracket/" + type + "/" + (vertical ? "ground" : "wall");
return prov.models()
.withExistingParent(path + "_" + material, prov.modLoc(path))
.texture("bracket", prov.modLoc("block/bracket_" + material))
.texture("plate", prov.modLoc("block/bracket_plate_" + material));
}
public static <I extends BlockItem, P> NonNullFunction<ItemBuilder<I, P>, P> itemModel(String material) {
return b -> b.model((c, p) -> p.withExistingParent(c.getName(), p.modLoc("block/bracket/item"))
.texture("bracket", p.modLoc("block/bracket_" + material))
.texture("plate", p.modLoc("block/bracket_plate_" + material)))
.build();
}
}

View file

@ -1,5 +1,6 @@
package com.simibubi.create.content.contraptions.fluids.pipes;
import java.util.Optional;
import java.util.Random;
import javax.annotation.Nullable;
@ -8,18 +9,20 @@ 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.content.contraptions.wrench.IWrenchableWithBracket;
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.Blocks;
import net.minecraft.block.IWaterLoggable;
import net.minecraft.block.SixWayBlock;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.fluid.FluidState;
import net.minecraft.fluid.Fluids;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUseContext;
import net.minecraft.network.DebugPacketSender;
import net.minecraft.state.StateContainer.Builder;
@ -39,7 +42,7 @@ 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 class FluidPipeBlock extends SixWayBlock implements IWaterLoggable, IWrenchableWithBracket {
public FluidPipeBlock(Properties properties) {
super(4 / 16f, properties);
@ -48,6 +51,9 @@ public class FluidPipeBlock extends SixWayBlock implements IWaterLoggable, IWren
@Override
public ActionResultType onWrenched(BlockState state, ItemUseContext context) {
if (tryRemoveBracket(context))
return ActionResultType.SUCCESS;
World world = context.getWorld();
BlockPos pos = context.getPos();
Axis axis = getAxis(world, pos, state);
@ -78,16 +84,7 @@ public class FluidPipeBlock extends SixWayBlock implements IWaterLoggable, IWren
@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;
return FluidPropagator.getStraightPipeAxis(state);
}
@Override
@ -105,6 +102,8 @@ public class FluidPipeBlock extends SixWayBlock implements IWaterLoggable, IWren
boolean blockTypeChanged = state.getBlock() != newState.getBlock();
if (blockTypeChanged && !world.isRemote)
FluidPropagator.propagateChangedPipe(world, pos, state);
if (state != newState && !isMoving)
removeBracket(world, pos).ifPresent(stack -> Block.spawnAsEntity(world, pos, stack));
if (state.hasTileEntity() && (blockTypeChanged || !newState.hasTileEntity()))
world.removeTileEntity(pos);
}
@ -140,24 +139,31 @@ public class FluidPipeBlock extends SixWayBlock implements IWaterLoggable, IWren
return state.getBlock() instanceof FluidPipeBlock;
}
public static boolean canConnectTo(IBlockDisplayReader world, BlockPos pos, BlockState neighbour, Direction blockFace) {
if (isPipe(neighbour) || FluidPropagator.hasFluidCapability(neighbour, world, pos, blockFace))
public static boolean canConnectTo(IBlockDisplayReader world, BlockPos pos, BlockState neighbour,
Direction blockFace) {
if (FluidPropagator.hasFluidCapability(neighbour, world, pos, blockFace))
return true;
FluidPipeAttachmentBehaviour attachmentBehaviour =
TileEntityBehaviour.get(world, pos, FluidPipeAttachmentBehaviour.TYPE);
if (isPipe(neighbour))
return attachmentBehaviour == null || attachmentBehaviour.getBracket() == Blocks.AIR.getDefaultState()
|| FluidPropagator.getStraightPipeAxis(neighbour) == blockFace.getAxis();
if (attachmentBehaviour == null)
return false;
return attachmentBehaviour.isPipeConnectedTowards(neighbour, blockFace);
}
public static boolean shouldDrawRim(IBlockDisplayReader world, BlockPos pos, BlockState state, Direction direction) {
public static boolean shouldDrawRim(IBlockDisplayReader world, BlockPos pos, BlockState state,
Direction direction) {
BlockPos offsetPos = pos.offset(direction);
BlockState facingState = world.getBlockState(offsetPos);
if (!isPipe(facingState))
return true;
if (!canConnectTo(world, offsetPos, facingState, direction))
return true;
if (!isCornerOrEndPipe(world, pos, state))
return false;
if (FluidPropagator.isStraightPipe(facingState))
if (FluidPropagator.getStraightPipeAxis(facingState) != null)
return true;
if (!shouldDrawCasing(world, pos, state) && shouldDrawCasing(world, offsetPos, facingState))
return true;
@ -171,7 +177,8 @@ public class FluidPipeBlock extends SixWayBlock implements IWaterLoggable, IWren
}
public static boolean isCornerOrEndPipe(IBlockDisplayReader world, BlockPos pos, BlockState state) {
return isPipe(state) && !FluidPropagator.isStraightPipe(state) && !shouldDrawCasing(world, pos, state);
return isPipe(state) && FluidPropagator.getStraightPipeAxis(state) == null
&& !shouldDrawCasing(world, pos, state);
}
public static boolean shouldDrawCasing(IBlockDisplayReader world, BlockPos pos, BlockState state) {
@ -206,20 +213,28 @@ public class FluidPipeBlock extends SixWayBlock implements IWaterLoggable, IWren
@Override
public BlockState updatePostPlacement(BlockState state, Direction direction, BlockState neighbourState,
IWorld world, BlockPos pos, BlockPos neighbourPos) {
if (state.get(BlockStateProperties.WATERLOGGED)) {
if (state.get(BlockStateProperties.WATERLOGGED))
world.getPendingFluidTicks()
.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickRate(world));
}
if (isOpenAt(state, direction) && neighbourState.contains(BlockStateProperties.WATERLOGGED))
world.getPendingBlockTicks()
.scheduleTick(pos, this, 1, TickPriority.HIGH);
return updateBlockState(state, direction, direction.getOpposite(), world, pos);
}
public BlockState updateBlockState(BlockState state, Direction preferredDirection, @Nullable Direction ignore,
IBlockDisplayReader world, BlockPos pos) {
FluidPipeAttachmentBehaviour behaviour = TileEntityBehaviour.get(world, pos, FluidPipeAttachmentBehaviour.TYPE);
if (behaviour != null && behaviour.getBracket() != Blocks.AIR.getDefaultState())
return state;
// 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));
if (d != ignore) {
boolean shouldConnect = canConnectTo(world, pos.offset(d), world.getBlockState(pos.offset(d)), d);
state = state.with(FACING_TO_PROPERTY_MAP.get(d), shouldConnect);
}
// See if it has enough connections
Direction connectedDirection = null;
@ -245,4 +260,16 @@ public class FluidPipeBlock extends SixWayBlock implements IWaterLoggable, IWren
return state.get(BlockStateProperties.WATERLOGGED) ? Fluids.WATER.getStillFluidState(false)
: Fluids.EMPTY.getDefaultState();
}
@Override
public Optional<ItemStack> removeBracket(IBlockReader world, BlockPos pos) {
FluidPipeAttachmentBehaviour behaviour = TileEntityBehaviour.get(world, pos, FluidPipeAttachmentBehaviour.TYPE);
if (behaviour == null)
return Optional.empty();
BlockState bracket = behaviour.getBracket();
behaviour.removeBracket();
if (bracket == Blocks.AIR.getDefaultState())
return Optional.empty();
return Optional.of(new ItemStack(bracket.getBlock()));
}
}

View file

@ -39,12 +39,11 @@ public class GlassFluidPipeBlock extends AxisPipeBlock {
@Override
public ActionResultType onWrenched(BlockState state, ItemUseContext context) {
if (tryRemoveBracket(context))
return ActionResultType.SUCCESS;
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;

View file

@ -16,7 +16,7 @@ import net.minecraft.util.math.vector.Vector3i;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
public class AirFlowParticleData implements IParticleData, ICustomParticle<AirFlowParticleData> {
public class AirFlowParticleData implements IParticleData, ICustomParticleDataWithSprite<AirFlowParticleData> {
public static final Codec<AirFlowParticleData> CODEC = RecordCodecBuilder.create(i ->
i.group(
@ -83,13 +83,13 @@ public class AirFlowParticleData implements IParticleData, ICustomParticle<AirFl
}
@Override
public Codec<AirFlowParticleData> getCodec() {
public Codec<AirFlowParticleData> getCodec(ParticleType<AirFlowParticleData> type) {
return CODEC;
}
@Override
@OnlyIn(Dist.CLIENT)
public IParticleMetaFactory<AirFlowParticleData> getFactory() {
public IParticleMetaFactory<AirFlowParticleData> getMetaFactory() {
return AirFlowParticle.Factory::new;
}

View file

@ -15,7 +15,7 @@ import net.minecraft.particles.ParticleType;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
public class AirParticleData implements IParticleData, ICustomParticle<AirParticleData> {
public class AirParticleData implements IParticleData, ICustomParticleDataWithSprite<AirParticleData> {
public static final Codec<AirParticleData> CODEC = RecordCodecBuilder.create(i ->
i.group(
@ -79,7 +79,7 @@ public class AirParticleData implements IParticleData, ICustomParticle<AirPartic
@Override
@OnlyIn(Dist.CLIENT)
public IParticleMetaFactory<AirParticleData> getFactory() {
public IParticleMetaFactory<AirParticleData> getMetaFactory() {
return AirParticle.Factory::new;
}

View file

@ -8,14 +8,14 @@ import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import com.simibubi.create.AllParticleTypes;
import net.minecraft.client.particle.ParticleManager;
import net.minecraft.client.particle.IParticleFactory;
import net.minecraft.network.PacketBuffer;
import net.minecraft.particles.IParticleData;
import net.minecraft.particles.ParticleType;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
public class CubeParticleData implements IParticleData, ICustomParticle<CubeParticleData> {
public class CubeParticleData implements IParticleData, ICustomParticleData<CubeParticleData> {
public static final Codec<CubeParticleData> CODEC = RecordCodecBuilder.create(i ->
i.group(
@ -67,8 +67,8 @@ public class CubeParticleData implements IParticleData, ICustomParticle<CubePart
this.hot = hot;
}
public static CubeParticleData dummy() {
return new CubeParticleData(0, 0, 0, 0, 0, false);
public CubeParticleData() {
this(0, 0, 0, 0, 0, false);
}
@Override
@ -83,8 +83,8 @@ public class CubeParticleData implements IParticleData, ICustomParticle<CubePart
@Override
@OnlyIn(Dist.CLIENT)
public ParticleManager.IParticleMetaFactory<CubeParticleData> getFactory() {
return null;
public IParticleFactory<CubeParticleData> getFactory() {
return new CubeParticle.Factory();
}
@Override

View file

@ -20,7 +20,7 @@ import net.minecraftforge.api.distmarker.OnlyIn;
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
public class HeaterParticleData implements IParticleData, ICustomParticle<HeaterParticleData> {
public class HeaterParticleData implements IParticleData, ICustomParticleDataWithSprite<HeaterParticleData> {
public static final Codec<HeaterParticleData> CODEC = RecordCodecBuilder.create(i ->
i.group(
@ -75,7 +75,7 @@ public class HeaterParticleData implements IParticleData, ICustomParticle<Heater
@Override
@OnlyIn(Dist.CLIENT)
public IParticleMetaFactory<HeaterParticleData> getFactory() {
public IParticleMetaFactory<HeaterParticleData> getMetaFactory() {
return HeaterParticle.Factory::new;
}

View file

@ -2,30 +2,36 @@ package com.simibubi.create.content.contraptions.particle;
import com.mojang.serialization.Codec;
import net.minecraft.client.particle.ParticleManager.IParticleMetaFactory;
import net.minecraft.client.particle.IParticleFactory;
import net.minecraft.client.particle.ParticleManager;
import net.minecraft.particles.IParticleData;
import net.minecraft.particles.IParticleData.IDeserializer;
import net.minecraft.particles.ParticleType;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
public interface ICustomParticle<T extends IParticleData> {
public interface ICustomParticleData<T extends IParticleData> {
IDeserializer<T> getDeserializer();
Codec<T> getCodec();
Codec<T> getCodec(ParticleType<T> type);
public default ParticleType<T> createType() {
return new ParticleType<T>(false, getDeserializer()) {
@Override
public Codec<T> getCodec() {
return ICustomParticle.this.getCodec();
return ICustomParticleData.this.getCodec(this);
}
};
}
@OnlyIn(Dist.CLIENT)
public IParticleMetaFactory<T> getFactory();
public IParticleFactory<T> getFactory();
@OnlyIn(Dist.CLIENT)
public default void register(ParticleType<T> type, ParticleManager particles) {
particles.registerFactory(type, getFactory());
}
}

View file

@ -0,0 +1,34 @@
package com.simibubi.create.content.contraptions.particle;
import net.minecraft.client.particle.IParticleFactory;
import net.minecraft.client.particle.ParticleManager;
import net.minecraft.client.particle.ParticleManager.IParticleMetaFactory;
import net.minecraft.particles.IParticleData;
import net.minecraft.particles.IParticleData.IDeserializer;
import net.minecraft.particles.ParticleType;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
public interface ICustomParticleDataWithSprite<T extends IParticleData> extends ICustomParticleData<T> {
public IDeserializer<T> getDeserializer();
public default ParticleType<T> createType() {
return new ParticleType<T>(false, getDeserializer());
}
@Override
default IParticleFactory<T> getFactory() {
throw new IllegalAccessError("This particle type uses a metaFactory!");
}
@OnlyIn(Dist.CLIENT)
public IParticleMetaFactory<T> getMetaFactory();
@Override
@OnlyIn(Dist.CLIENT)
public default void register(ParticleType<T> type, ParticleManager particles) {
particles.registerFactory(type, getMetaFactory());
}
}

View file

@ -19,63 +19,69 @@ import net.minecraft.util.Direction.Axis;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
public class RotationIndicatorParticleData implements IParticleData, ICustomParticle<RotationIndicatorParticleData> {
public class RotationIndicatorParticleData
implements IParticleData, ICustomParticleDataWithSprite<RotationIndicatorParticleData> {
// TODO 1.16 make this unnecessary
public static final PrimitiveCodec<Character> CHAR = new PrimitiveCodec<Character>() {
@Override
public <T> DataResult<Character> read(final DynamicOps<T> ops, final T input) {
return ops
.getNumberValue(input)
.map(n -> (char) n.shortValue());
}
@Override
public <T> T write(final DynamicOps<T> ops, final Character value) {
return ops.createShort((short) value.charValue());
}
@Override
public String toString() {
return "Bool";
}
};
public static final Codec<RotationIndicatorParticleData> CODEC = RecordCodecBuilder.create(i ->
i.group(
Codec.INT.fieldOf("color").forGetter(p -> p.color),
Codec.FLOAT.fieldOf("speed").forGetter(p -> p.speed),
Codec.FLOAT.fieldOf("radius1").forGetter(p -> p.radius1),
Codec.FLOAT.fieldOf("radius2").forGetter(p -> p.radius2),
Codec.INT.fieldOf("lifeSpan").forGetter(p -> p.lifeSpan),
CHAR.fieldOf("axis").forGetter(p -> p.axis))
.apply(i, RotationIndicatorParticleData::new));
public static final IParticleData.IDeserializer<RotationIndicatorParticleData> DESERIALIZER = new IParticleData.IDeserializer<RotationIndicatorParticleData>() {
public RotationIndicatorParticleData deserialize(ParticleType<RotationIndicatorParticleData> particleTypeIn,
StringReader reader) throws CommandSyntaxException {
reader.expect(' ');
int color = reader.readInt();
reader.expect(' ');
float speed = (float) reader.readDouble();
reader.expect(' ');
float rad1 = (float) reader.readDouble();
reader.expect(' ');
float rad2 = (float) reader.readDouble();
reader.expect(' ');
int lifeSpan = reader.readInt();
reader.expect(' ');
char axis = reader.read();
return new RotationIndicatorParticleData(color, speed, rad1, rad2, lifeSpan, axis);
@Override
public <T> DataResult<Character> read(final DynamicOps<T> ops, final T input) {
return ops.getNumberValue(input)
.map(n -> (char) n.shortValue());
}
public RotationIndicatorParticleData read(ParticleType<RotationIndicatorParticleData> particleTypeIn,
PacketBuffer buffer) {
return new RotationIndicatorParticleData(buffer.readInt(), buffer.readFloat(), buffer.readFloat(),
buffer.readFloat(), buffer.readInt(), buffer.readChar());
@Override
public <T> T write(final DynamicOps<T> ops, final Character value) {
return ops.createShort((short) value.charValue());
}
@Override
public String toString() {
return "Bool";
}
};
public static final Codec<RotationIndicatorParticleData> CODEC = RecordCodecBuilder.create(i -> i
.group(Codec.INT.fieldOf("color")
.forGetter(p -> p.color),
Codec.FLOAT.fieldOf("speed")
.forGetter(p -> p.speed),
Codec.FLOAT.fieldOf("radius1")
.forGetter(p -> p.radius1),
Codec.FLOAT.fieldOf("radius2")
.forGetter(p -> p.radius2),
Codec.INT.fieldOf("lifeSpan")
.forGetter(p -> p.lifeSpan),
CHAR.fieldOf("axis")
.forGetter(p -> p.axis))
.apply(i, RotationIndicatorParticleData::new));
public static final IParticleData.IDeserializer<RotationIndicatorParticleData> DESERIALIZER =
new IParticleData.IDeserializer<RotationIndicatorParticleData>() {
public RotationIndicatorParticleData deserialize(ParticleType<RotationIndicatorParticleData> particleTypeIn,
StringReader reader) throws CommandSyntaxException {
reader.expect(' ');
int color = reader.readInt();
reader.expect(' ');
float speed = (float) reader.readDouble();
reader.expect(' ');
float rad1 = (float) reader.readDouble();
reader.expect(' ');
float rad2 = (float) reader.readDouble();
reader.expect(' ');
int lifeSpan = reader.readInt();
reader.expect(' ');
char axis = reader.read();
return new RotationIndicatorParticleData(color, speed, rad1, rad2, lifeSpan, axis);
}
public RotationIndicatorParticleData read(ParticleType<RotationIndicatorParticleData> particleTypeIn,
PacketBuffer buffer) {
return new RotationIndicatorParticleData(buffer.readInt(), buffer.readFloat(), buffer.readFloat(),
buffer.readFloat(), buffer.readInt(), buffer.readChar());
}
};
final int color;
final float speed;
final float radius1;
@ -84,7 +90,7 @@ public class RotationIndicatorParticleData implements IParticleData, ICustomPart
final char axis;
public RotationIndicatorParticleData(int color, float speed, float radius1, float radius2, int lifeSpan,
char axis) {
char axis) {
this.color = color;
this.speed = speed;
this.radius1 = radius1;
@ -119,7 +125,7 @@ public class RotationIndicatorParticleData implements IParticleData, ICustomPart
@Override
public String getParameters() {
return String.format(Locale.ROOT, "%s %d %.2f %.2f %.2f %d %c", AllParticleTypes.ROTATION_INDICATOR.parameter(),
color, speed, radius1, radius2, lifeSpan, axis);
color, speed, radius1, radius2, lifeSpan, axis);
}
@Override
@ -128,13 +134,13 @@ public class RotationIndicatorParticleData implements IParticleData, ICustomPart
}
@Override
public Codec<RotationIndicatorParticleData> getCodec() {
public Codec<RotationIndicatorParticleData> getCodec(ParticleType<RotationIndicatorParticleData> type) {
return CODEC;
}
@Override
@OnlyIn(Dist.CLIENT)
public IParticleMetaFactory<RotationIndicatorParticleData> getFactory() {
public IParticleMetaFactory<RotationIndicatorParticleData> getMetaFactory() {
return RotationIndicatorParticle.Factory::new;
}

View file

@ -7,17 +7,23 @@ import com.simibubi.create.foundation.fluid.FluidRenderer;
import com.simibubi.create.foundation.tileEntity.behaviour.fluid.SmartFluidTankBehaviour;
import com.simibubi.create.foundation.tileEntity.behaviour.fluid.SmartFluidTankBehaviour.TankSegment;
import com.simibubi.create.foundation.tileEntity.renderer.SmartTileEntityRenderer;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.IntAttached;
import com.simibubi.create.foundation.utility.MatrixStacker;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType;
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.util.math.vector.Vector3f;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.items.IItemHandlerModifiable;
import net.minecraftforge.items.ItemStackHandler;
@ -33,35 +39,94 @@ public class BasinRenderer extends SmartTileEntityRenderer<BasinTileEntity> {
int light, int overlay) {
super.renderSafe(basin, partialTicks, ms, buffer, light, overlay);
renderFluids(basin, partialTicks, ms, buffer, light, overlay);
float fluidLevel = renderFluids(basin, partialTicks, ms, buffer, light, overlay);
float level = MathHelper.clamp(fluidLevel - .3f, .125f, .6f);
ms.push();
BlockPos pos = basin.getPos();
ms.translate(.5, .2f, .5);
MatrixStacker.of(ms)
.rotateY(basin.ingredientRotation.getValue(partialTicks));
Random r = new Random(pos.hashCode());
Vector3d baseVector = new Vector3d(.125, level, 0);
IItemHandlerModifiable inv = basin.itemCapability.orElse(new ItemStackHandler());
int itemCount = 0;
for (int slot = 0; slot < inv.getSlots(); slot++)
if (!inv.getStackInSlot(slot)
.isEmpty())
itemCount++;
if (itemCount == 1)
baseVector = new Vector3d(0, level, 0);
float anglePartition = 360f / itemCount;
for (int slot = 0; slot < inv.getSlots(); slot++) {
ItemStack stack = inv.getStackInSlot(slot);
if (stack.isEmpty())
continue;
ms.push();
if (fluidLevel > 0) {
ms.translate(0,
(MathHelper.sin(AnimationTickHolder.getRenderTick() / 12f + anglePartition * itemCount) + 1.5f) * 1
/ 32f,
0);
}
Vector3d itemPosition = VecHelper.rotate(baseVector, anglePartition * itemCount, Axis.Y);
ms.translate(itemPosition.x, itemPosition.y, itemPosition.z);
MatrixStacker.of(ms)
.rotateY(anglePartition * itemCount + 35)
.rotateX(65);
for (int i = 0; i <= stack.getCount() / 8; i++) {
ms.push();
Vector3d vec = VecHelper.offsetRandomly(Vector3d.ZERO, r, .25f);
Vector3d vec2 = VecHelper.offsetRandomly(Vector3d.ZERO, r, .5f);
ms.translate(vec.x, vec.y, vec.z);
ms.multiply(new Vector3f((float) vec2.z, (float) vec2.y, 0).getDegreesQuaternion((float) vec2.x * 180));
Minecraft.getInstance()
.getItemRenderer()
.renderItem(stack, TransformType.GROUND, light, overlay, ms, buffer);
Vector3d vec = VecHelper.offsetRandomly(Vector3d.ZERO, r, 1 / 16f);
ms.translate(vec.x, vec.y, vec.z);
renderItem(ms, buffer, light, overlay, stack);
ms.pop();
}
ms.translate(0, 1 / 64f, 0);
ms.pop();
itemCount--;
}
ms.pop();
BlockState blockState = basin.getBlockState();
if (!(blockState.getBlock() instanceof BasinBlock))
return;
Direction direction = blockState.get(BasinBlock.FACING);
if (direction == Direction.DOWN)
return;
Vector3d directionVec = Vector3d.of(direction.getDirectionVec());
Vector3d outVec = VecHelper.getCenterOf(BlockPos.ZERO)
.add(directionVec.scale(.55)
.subtract(0, 1 / 2f, 0));
for (IntAttached<ItemStack> intAttached : basin.visualizedOutputItems) {
float progress = 1 - (intAttached.getFirst() - partialTicks) / BasinTileEntity.OUTPUT_ANIMATION_TIME;
ms.push();
MatrixStacker.of(ms)
.translate(outVec)
.translate(new Vector3d(0, Math.max(-.55f, -(progress * progress * 2)), 0))
.translate(directionVec.scale(progress * .5f))
.rotateY(AngleHelper.horizontalAngle(direction))
.rotateX(progress * 180);
renderItem(ms, buffer, light, overlay, intAttached.getValue());
ms.pop();
}
}
protected void renderItem(MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay, ItemStack stack) {
Minecraft.getInstance()
.getItemRenderer()
.renderItem(stack, TransformType.GROUND, light, overlay, ms, buffer);
}
protected float renderFluids(BasinTileEntity basin, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer,
@ -69,26 +134,7 @@ public class BasinRenderer extends SmartTileEntityRenderer<BasinTileEntity> {
SmartFluidTankBehaviour inputFluids = basin.getBehaviour(SmartFluidTankBehaviour.INPUT);
SmartFluidTankBehaviour outputFluids = basin.getBehaviour(SmartFluidTankBehaviour.OUTPUT);
SmartFluidTankBehaviour[] tanks = { inputFluids, outputFluids };
int renderedFluids = 0;
float totalUnits = 0;
for (SmartFluidTankBehaviour behaviour : tanks) {
if (behaviour == null)
continue;
for (TankSegment tankSegment : behaviour.getTanks()) {
if (tankSegment.getRenderedFluid()
.isEmpty())
continue;
float units = tankSegment.getTotalUnits(partialTicks);
if (units < 1)
continue;
totalUnits += units;
renderedFluids++;
}
}
if (renderedFluids == 0)
return 0;
float totalUnits = basin.getTotalFluidUnits();
if (totalUnits < 1)
return 0;
@ -112,7 +158,7 @@ public class BasinRenderer extends SmartTileEntityRenderer<BasinTileEntity> {
if (units < 1)
continue;
float partial = units / totalUnits;
float partial = MathHelper.clamp(units / totalUnits, 0, 1);
xMax += partial * 12 / 16f;
FluidRenderer.renderTiledFluidBB(renderedFluid, xMin, yMin, zMin, xMax, yMax, zMax, buffer, ms, light,
false);
@ -121,7 +167,7 @@ public class BasinRenderer extends SmartTileEntityRenderer<BasinTileEntity> {
}
}
return fluidLevel;
return yMax;
}
}

View file

@ -1,11 +1,18 @@
package com.simibubi.create.content.contraptions.processing;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.Random;
import javax.annotation.Nonnull;
import com.simibubi.create.AllParticleTypes;
import com.simibubi.create.AllTags;
import com.simibubi.create.content.contraptions.components.mixer.MechanicalMixerTileEntity;
import com.simibubi.create.content.contraptions.fluids.FluidFX;
import com.simibubi.create.content.contraptions.fluids.particle.FluidParticleData;
import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock;
import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock.HeatLevel;
import com.simibubi.create.foundation.fluid.CombinedTankWrapper;
@ -16,22 +23,33 @@ import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform;
import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour;
import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour;
import com.simibubi.create.foundation.tileEntity.behaviour.fluid.SmartFluidTankBehaviour;
import com.simibubi.create.foundation.tileEntity.behaviour.fluid.SmartFluidTankBehaviour.TankSegment;
import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.BlockHelper;
import com.simibubi.create.foundation.utility.Couple;
import com.simibubi.create.foundation.utility.IntAttached;
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.VecHelper;
import net.minecraft.block.BlockState;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.particles.IParticleData;
import net.minecraft.tileentity.ITickableTileEntity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.vector.Vector3d;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.Constants.NBT;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
@ -45,25 +63,44 @@ import net.minecraftforge.items.wrapper.CombinedInvWrapper;
public class BasinTileEntity extends SmartTileEntity implements ITickableTileEntity {
private boolean areFluidsMoving;
LerpedFloat ingredientRotationSpeed;
LerpedFloat ingredientRotation;
public BasinInventory inputInventory;
public SmartFluidTankBehaviour inputTank;
protected SmartInventory outputInventory;
protected SmartFluidTankBehaviour outputTank;
private FilteringBehaviour filtering;
private boolean contentsChanged;
private Couple<SmartInventory> invs;
private Couple<SmartFluidTankBehaviour> tanks;
protected LazyOptional<IItemHandlerModifiable> itemCapability;
protected LazyOptional<IFluidHandler> fluidCapability;
private FilteringBehaviour filtering;
private boolean contentsChanged;
public static final int OUTPUT_ANIMATION_TIME = 10;
List<IntAttached<ItemStack>> visualizedOutputItems;
List<IntAttached<FluidStack>> visualizedOutputFluids;
public BasinTileEntity(TileEntityType<? extends BasinTileEntity> type) {
super(type);
inputInventory = new BasinInventory(9, this);
inputInventory.whenContentsChanged($ -> contentsChanged = true);
outputInventory = new BasinInventory(9, this).forbidInsertion();
areFluidsMoving = false;
itemCapability = LazyOptional.of(() -> new CombinedInvWrapper(inputInventory, outputInventory));
contentsChanged = true;
ingredientRotation = LerpedFloat.angular()
.startWithValue(0);
ingredientRotationSpeed = LerpedFloat.linear()
.startWithValue(0);
invs = Couple.create(inputInventory, outputInventory);
tanks = Couple.create(inputTank, outputTank);
visualizedOutputItems = Collections.synchronizedList(new ArrayList<>());
visualizedOutputFluids = Collections.synchronizedList(new ArrayList<>());
}
@Override
@ -79,6 +116,7 @@ public class BasinTileEntity extends SmartTileEntity implements ITickableTileEnt
outputTank = new SmartFluidTankBehaviour(SmartFluidTankBehaviour.OUTPUT, this, 2, 1000, true).forbidInsertion();
behaviours.add(inputTank);
behaviours.add(outputTank);
fluidCapability = LazyOptional.of(() -> {
LazyOptional<? extends IFluidHandler> inputCap = inputTank.getCapability();
LazyOptional<? extends IFluidHandler> outputCap = outputTank.getCapability();
@ -91,6 +129,15 @@ public class BasinTileEntity extends SmartTileEntity implements ITickableTileEnt
super.fromTag(state, compound, clientPacket);
inputInventory.deserializeNBT(compound.getCompound("InputItems"));
outputInventory.deserializeNBT(compound.getCompound("OutputItems"));
if (!clientPacket)
return;
NBTHelper.iterateCompoundList(compound.getList("VisualizedItems", NBT.TAG_COMPOUND),
c -> visualizedOutputItems.add(IntAttached.with(OUTPUT_ANIMATION_TIME, ItemStack.read(c))));
NBTHelper.iterateCompoundList(compound.getList("VisualizedFluids", NBT.TAG_COMPOUND),
c -> visualizedOutputFluids
.add(IntAttached.with(OUTPUT_ANIMATION_TIME, FluidStack.loadFluidStackFromNBT(c))));
}
@Override
@ -98,6 +145,16 @@ public class BasinTileEntity extends SmartTileEntity implements ITickableTileEnt
super.write(compound, clientPacket);
compound.put("InputItems", inputInventory.serializeNBT());
compound.put("OutputItems", outputInventory.serializeNBT());
if (!clientPacket)
return;
compound.put("VisualizedItems", NBTHelper.writeCompoundList(visualizedOutputItems, ia -> ia.getValue()
.serializeNBT()));
compound.put("VisualizedFluids", NBTHelper.writeCompoundList(visualizedOutputFluids, ia -> ia.getValue()
.writeToNBT(new CompoundNBT())));
visualizedOutputItems.clear();
visualizedOutputFluids.clear();
}
public void onEmptied() {
@ -130,11 +187,26 @@ public class BasinTileEntity extends SmartTileEntity implements ITickableTileEnt
@Override
public void lazyTick() {
super.lazyTick();
if (!world.isRemote)
return;
TileEntity tileEntity = world.getTileEntity(pos.up(2));
if (!(tileEntity instanceof MechanicalMixerTileEntity)) {
setAreFluidsMoving(false);
return;
}
MechanicalMixerTileEntity mixer = (MechanicalMixerTileEntity) tileEntity;
setAreFluidsMoving(mixer.running && mixer.runningTicks <= 20);
}
@Override
public void tick() {
super.tick();
if (world.isRemote) {
createFluidParticles();
tickVisualizedOutputs();
ingredientRotationSpeed.tickChaser();
ingredientRotation.setValue(ingredientRotation.getValue() + ingredientRotationSpeed.getValue());
}
if (!contentsChanged)
return;
contentsChanged = false;
@ -153,6 +225,32 @@ public class BasinTileEntity extends SmartTileEntity implements ITickableTileEnt
}
}
public float getTotalFluidUnits() {
int renderedFluids = 0;
float totalUnits = 0;
for (SmartFluidTankBehaviour behaviour : getTanks()) {
if (behaviour == null)
continue;
for (TankSegment tankSegment : behaviour.getTanks()) {
if (tankSegment.getRenderedFluid()
.isEmpty())
continue;
float units = tankSegment.getTotalUnits(0);
if (units < 1)
continue;
totalUnits += units;
renderedFluids++;
}
}
if (renderedFluids == 0)
return 0;
if (totalUnits < 1)
return 0;
return totalUnits;
}
private Optional<BasinOperatingTileEntity> getOperator() {
if (world == null)
return Optional.empty();
@ -226,6 +324,8 @@ public class BasinTileEntity extends SmartTileEntity implements ITickableTileEnt
if (!ItemHandlerHelper.insertItemStacked(targetInv, itemStack.copy(), simulate)
.isEmpty())
return false;
else if (!simulate)
visualizedOutputItems.add(IntAttached.withZero(itemStack));
if (targetTank == null)
return false;
@ -233,10 +333,145 @@ public class BasinTileEntity extends SmartTileEntity implements ITickableTileEnt
if (targetTank.fill(fluidStack.copy(), simulate ? FluidAction.SIMULATE : FluidAction.EXECUTE) != fluidStack
.getAmount())
return false;
else if (!simulate)
visualizedOutputFluids.add(IntAttached.withZero(fluidStack));
return true;
}
public void readOnlyItems(CompoundNBT compound) {
inputInventory.deserializeNBT(compound.getCompound("InputItems"));
outputInventory.deserializeNBT(compound.getCompound("OutputItems"));
}
public static HeatLevel getHeatLevelOf(BlockState state) {
if (BlockHelper.hasBlockStateProperty(state, BlazeBurnerBlock.HEAT_LEVEL))
return state.get(BlazeBurnerBlock.HEAT_LEVEL);
return AllTags.AllBlockTags.FAN_HEATERS.matches(state) ? HeatLevel.SMOULDERING : HeatLevel.NONE;
}
public Couple<SmartFluidTankBehaviour> getTanks() {
return tanks;
}
public Couple<SmartInventory> getInvs() {
return invs;
}
// client things
private void tickVisualizedOutputs() {
visualizedOutputFluids.forEach(IntAttached::decrement);
visualizedOutputItems.forEach(IntAttached::decrement);
visualizedOutputFluids.removeIf(IntAttached::isOrBelowZero);
visualizedOutputItems.removeIf(IntAttached::isOrBelowZero);
}
private void createFluidParticles() {
Random r = world.rand;
if (!visualizedOutputFluids.isEmpty())
createOutputFluidParticles(r);
if (!areFluidsMoving && r.nextFloat() > 1 / 8f)
return;
int segments = 0;
for (SmartFluidTankBehaviour behaviour : getTanks()) {
if (behaviour == null)
continue;
for (TankSegment tankSegment : behaviour.getTanks())
if (!tankSegment.isEmpty(0))
segments++;
}
if (segments < 2)
return;
float totalUnits = getTotalFluidUnits();
if (totalUnits == 0)
return;
float fluidLevel = MathHelper.clamp(totalUnits / 2000, 0, 1);
float rim = 2 / 16f;
float space = 12 / 16f;
float surface = pos.getY() + rim + space * fluidLevel + 1 / 32f;
if (areFluidsMoving) {
createMovingFluidParticles(surface, segments);
return;
}
for (SmartFluidTankBehaviour behaviour : getTanks()) {
if (behaviour == null)
continue;
for (TankSegment tankSegment : behaviour.getTanks()) {
if (tankSegment.isEmpty(0))
continue;
float x = pos.getX() + rim + space * r.nextFloat();
float z = pos.getZ() + rim + space * r.nextFloat();
world.addOptionalParticle(
new FluidParticleData(AllParticleTypes.BASIN_FLUID.get(), tankSegment.getRenderedFluid()), x,
surface, z, 0, 0, 0);
}
}
}
private void createOutputFluidParticles(Random r) {
BlockState blockState = getBlockState();
if (!(blockState.getBlock() instanceof BasinBlock))
return;
Direction direction = blockState.get(BasinBlock.FACING);
if (direction == Direction.DOWN)
return;
Vector3d directionVec = Vector3d.of(direction.getDirectionVec());
Vector3d outVec = VecHelper.getCenterOf(pos)
.add(directionVec.scale(.65)
.subtract(0, 1 / 4f, 0));
Vector3d outMotion = directionVec.scale(1 / 16f)
.add(0, -1 / 16f, 0);
for (int i = 0; i < 3; i++) {
visualizedOutputFluids.forEach(ia -> {
FluidStack fluidStack = ia.getValue();
IParticleData fluidParticle = FluidFX.getFluidParticle(fluidStack);
Vector3d m = VecHelper.offsetRandomly(outMotion, r, 1 / 16f);
world.addOptionalParticle(fluidParticle, outVec.x, outVec.y, outVec.z, m.x, m.y, m.z);
});
}
}
private void createMovingFluidParticles(float surface, int segments) {
Vector3d pointer = new Vector3d(1, 0, 0).scale(1 / 16f);
float interval = 360f / segments;
Vector3d centerOf = VecHelper.getCenterOf(pos);
float intervalOffset = (AnimationTickHolder.ticks * 18) % 360;
int currentSegment = 0;
for (SmartFluidTankBehaviour behaviour : getTanks()) {
if (behaviour == null)
continue;
for (TankSegment tankSegment : behaviour.getTanks()) {
if (tankSegment.isEmpty(0))
continue;
float angle = interval * (1 + currentSegment) + intervalOffset;
Vector3d vec = centerOf.add(VecHelper.rotate(pointer, angle, Axis.Y));
world.addOptionalParticle(
new FluidParticleData(AllParticleTypes.BASIN_FLUID.get(), tankSegment.getRenderedFluid()),
vec.getX(), surface, vec.getZ(), 1, 0, 0);
currentSegment++;
}
}
}
public boolean areFluidsMoving() {
return areFluidsMoving;
}
public boolean setAreFluidsMoving(boolean areFluidsMoving) {
this.areFluidsMoving = areFluidsMoving;
ingredientRotationSpeed.chase(areFluidsMoving ? 20 : 0, .1f, Chaser.EXP);
return areFluidsMoving;
}
class BasinValueBox extends ValueBoxTransform.Sided {
@Override
@ -251,15 +486,4 @@ public class BasinTileEntity extends SmartTileEntity implements ITickableTileEnt
}
}
public void readOnlyItems(CompoundNBT compound) {
inputInventory.deserializeNBT(compound.getCompound("InputItems"));
outputInventory.deserializeNBT(compound.getCompound("OutputItems"));
}
public static HeatLevel getHeatLevelOf(BlockState state) {
if (BlockHelper.hasBlockStateProperty(state, BlazeBurnerBlock.HEAT_LEVEL))
return state.get(BlazeBurnerBlock.HEAT_LEVEL);
return AllTags.AllBlockTags.FAN_HEATERS.matches(state) ? HeatLevel.SMOULDERING : HeatLevel.NONE;
}
}

View file

@ -0,0 +1,80 @@
package com.simibubi.create.content.contraptions.relays.elementary;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import com.simibubi.create.foundation.block.render.WrappedBakedModel;
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
import com.simibubi.create.foundation.utility.VirtualEmptyModelData;
import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.model.BakedQuad;
import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.ILightReader;
import net.minecraftforge.client.model.data.IModelData;
import net.minecraftforge.client.model.data.ModelDataMap;
import net.minecraftforge.client.model.data.ModelProperty;
public class BracketedKineticBlockModel extends WrappedBakedModel {
private static ModelProperty<BracketedModelData> BRACKET_PROPERTY = new ModelProperty<>();
public BracketedKineticBlockModel(IBakedModel template) {
super(template);
}
@Override
public IModelData getModelData(ILightReader world, BlockPos pos, BlockState state, IModelData tileData) {
if (tileData == VirtualEmptyModelData.INSTANCE)
return tileData;
BracketedModelData data = new BracketedModelData();
BracketedTileEntityBehaviour attachmentBehaviour =
TileEntityBehaviour.get(world, pos, BracketedTileEntityBehaviour.TYPE);
if (attachmentBehaviour != null)
data.putBracket(attachmentBehaviour.getBracket());
return new ModelDataMap.Builder().withInitial(BRACKET_PROPERTY, data)
.build();
}
@Override
public List<BakedQuad> getQuads(BlockState state, Direction side, Random rand, IModelData data) {
if (data instanceof ModelDataMap) {
List<BakedQuad> quads = new ArrayList<>();
ModelDataMap modelDataMap = (ModelDataMap) data;
if (modelDataMap.hasProperty(BRACKET_PROPERTY)) {
quads = new ArrayList<>(quads);
addQuads(quads, state, side, rand, modelDataMap, modelDataMap.getData(BRACKET_PROPERTY));
}
return quads;
}
return super.getQuads(state, side, rand, data);
}
private void addQuads(List<BakedQuad> quads, BlockState state, Direction side, Random rand, IModelData data,
BracketedModelData pipeData) {
IBakedModel bracket = pipeData.getBracket();
if (bracket == null)
return;
quads.addAll(bracket.getQuads(state, side, rand, data));
}
private class BracketedModelData {
IBakedModel bracket;
public void putBracket(BlockState state) {
this.bracket = Minecraft.getInstance()
.getBlockRendererDispatcher()
.getModelForState(state);
}
public IBakedModel getBracket() {
return bracket;
}
}
}

View file

@ -0,0 +1,75 @@
package com.simibubi.create.content.contraptions.relays.elementary;
import java.util.Optional;
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.NBTHelper;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.NBTUtil;
public class BracketedTileEntityBehaviour extends TileEntityBehaviour {
public static BehaviourType<BracketedTileEntityBehaviour> TYPE = new BehaviourType<>();
private Optional<BlockState> bracket;
private boolean reRender;
public BracketedTileEntityBehaviour(SmartTileEntity te) {
super(te);
bracket = Optional.empty();
}
@Override
public BehaviourType<?> getType() {
return TYPE;
}
public void applyBracket(BlockState state) {
this.bracket = Optional.of(state);
reRender = true;
tileEntity.notifyUpdate();
}
public void removeBracket() {
this.bracket = Optional.empty();
reRender = true;
tileEntity.notifyUpdate();
}
public BlockState getBracket() {
return bracket.orElse(Blocks.AIR.getDefaultState());
}
@Override
public void write(CompoundNBT nbt, boolean clientPacket) {
bracket.ifPresent(p -> nbt.put("Bracket", NBTUtil.writeBlockState(p)));
if (clientPacket && reRender) {
NBTHelper.putMarker(nbt, "Redraw");
reRender = false;
}
super.write(nbt, clientPacket);
}
@Override
public void read(CompoundNBT nbt, boolean clientPacket) {
bracket = Optional.empty();
if (nbt.contains("Bracket"))
bracket = Optional.of(NBTUtil.readBlockState(nbt.getCompound("Bracket")));
if (clientPacket && nbt.contains("Redraw"))
getWorld().notifyBlockUpdate(getPos(), tileEntity.getBlockState(), tileEntity.getBlockState(), 16);
super.read(nbt, clientPacket);
}
public boolean canHaveBracket() {
BlockState blockState = tileEntity.getBlockState();
if (blockState.getBlock() instanceof ShaftBlock)
return true;
return false;
}
}

View file

@ -1,15 +1,19 @@
package com.simibubi.create.content.contraptions.relays.elementary;
import java.util.Optional;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllShapes;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.base.RotatedPillarKineticBlock;
import com.simibubi.create.content.contraptions.relays.encased.EncasedShaftBlock;
import com.simibubi.create.content.contraptions.wrench.IWrenchableWithBracket;
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
import net.minecraft.block.Block;
import net.minecraft.block.BlockRenderType;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.IWaterLoggable;
import net.minecraft.block.material.PushReaction;
import net.minecraft.entity.player.PlayerEntity;
@ -35,107 +39,130 @@ import net.minecraft.world.IWorld;
import net.minecraft.world.IWorldReader;
import net.minecraft.world.World;
public class ShaftBlock extends RotatedPillarKineticBlock implements IWaterLoggable {
public class ShaftBlock extends RotatedPillarKineticBlock implements IWaterLoggable, IWrenchableWithBracket {
public ShaftBlock(Properties properties) {
super(properties);
setDefaultState(super.getDefaultState().with(BlockStateProperties.WATERLOGGED, false));
}
public ShaftBlock(Properties properties) {
super(properties);
setDefaultState(super.getDefaultState().with(BlockStateProperties.WATERLOGGED, false));
}
public static boolean isShaft(BlockState state) {
return AllBlocks.SHAFT.has(state);
}
public static boolean isShaft(BlockState state) {
return AllBlocks.SHAFT.has(state);
}
@Override
public PushReaction getPushReaction(BlockState state) {
return PushReaction.NORMAL;
}
@Override
public PushReaction getPushReaction(BlockState state) {
return PushReaction.NORMAL;
}
@Override
public BlockRenderType getRenderType(BlockState state) {
return BlockRenderType.ENTITYBLOCK_ANIMATED;
}
@Override
public TileEntity createTileEntity(BlockState state, IBlockReader world) {
return AllTileEntities.SIMPLE_KINETIC.create();
}
@Override
public TileEntity createTileEntity(BlockState state, IBlockReader world) {
return AllTileEntities.SIMPLE_KINETIC.create();
}
@Override
@SuppressWarnings("deprecation")
public void onReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean isMoving) {
if (state != newState && !isMoving)
removeBracket(world, pos).ifPresent(stack -> Block.spawnAsEntity(world, pos, stack));
super.onReplaced(state, world, pos, newState, isMoving);
}
@Override
public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) {
return AllShapes.SIX_VOXEL_POLE.get(state.get(AXIS));
}
@Override
public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) {
return AllShapes.SIX_VOXEL_POLE.get(state.get(AXIS));
}
@Override
public float getParticleTargetRadius() {
return .25f;
}
@Override
public float getParticleTargetRadius() {
return .25f;
}
@Override
public float getParticleInitialRadius() {
return 0f;
}
@Override
public float getParticleInitialRadius() {
return 0f;
}
@Override
public void fillItemGroup(ItemGroup group, NonNullList<ItemStack> items) {
super.fillItemGroup(group, items);
}
@Override
public void fillItemGroup(ItemGroup group, NonNullList<ItemStack> items) {
super.fillItemGroup(group, items);
}
@Override
public ActionResultType onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockRayTraceResult p_225533_6_) {
if (player.isSneaking() || !player.isAllowEdit())
return ActionResultType.PASS;
@Override
public ActionResultType onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand,
BlockRayTraceResult p_225533_6_) {
if (player.isSneaking() || !player.isAllowEdit())
return ActionResultType.PASS;
ItemStack heldItem = player.getHeldItem(hand);
ItemStack heldItem = player.getHeldItem(hand);
for (EncasedShaftBlock.Casing casing : EncasedShaftBlock.Casing.values()) {
if (casing.getCasingEntry().isIn(heldItem)) {
if (world.isRemote)
return ActionResultType.SUCCESS;
for (EncasedShaftBlock.Casing casing : EncasedShaftBlock.Casing.values()) {
if (casing.getCasingEntry()
.isIn(heldItem)) {
if (world.isRemote)
return ActionResultType.SUCCESS;
KineticTileEntity.switchToBlockState(world, pos, AllBlocks.ENCASED_SHAFT.getDefaultState().with(EncasedShaftBlock.CASING, casing).with(AXIS, state.get(AXIS)));
return ActionResultType.SUCCESS;
}
}
KineticTileEntity.switchToBlockState(world, pos, AllBlocks.ENCASED_SHAFT.getDefaultState()
.with(EncasedShaftBlock.CASING, casing)
.with(AXIS, state.get(AXIS)));
return ActionResultType.SUCCESS;
}
}
return ActionResultType.PASS;
}
return ActionResultType.PASS;
}
// IRotate:
// IRotate:
@Override
public boolean hasShaftTowards(IWorldReader world, BlockPos pos, BlockState state, Direction face) {
return face.getAxis() == state.get(AXIS);
}
@Override
public boolean hasShaftTowards(IWorldReader world, BlockPos pos, BlockState state, Direction face) {
return face.getAxis() == state.get(AXIS);
}
@Override
public Axis getRotationAxis(BlockState state) {
return state.get(AXIS);
}
@Override
public Axis getRotationAxis(BlockState state) {
return state.get(AXIS);
}
@Override
public FluidState getFluidState(BlockState state) {
return state.get(BlockStateProperties.WATERLOGGED) ? Fluids.WATER.getStillFluidState(false) : Fluids.EMPTY.getDefaultState();
}
@Override
public FluidState getFluidState(BlockState state) {
return state.get(BlockStateProperties.WATERLOGGED) ? Fluids.WATER.getStillFluidState(false)
: Fluids.EMPTY.getDefaultState();
}
@Override
protected void fillStateContainer(Builder<Block, BlockState> builder) {
builder.add(BlockStateProperties.WATERLOGGED);
super.fillStateContainer(builder);
}
@Override
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 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) {
FluidState FluidState = context.getWorld().getFluidState(context.getPos());
return super.getStateForPlacement(context).with(BlockStateProperties.WATERLOGGED, Boolean.valueOf(FluidState.getFluid() == Fluids.WATER));
}
@Override
public BlockState getStateForPlacement(BlockItemUseContext context) {
FluidState FluidState = context.getWorld()
.getFluidState(context.getPos());
return super.getStateForPlacement(context).with(BlockStateProperties.WATERLOGGED,
Boolean.valueOf(FluidState.getFluid() == Fluids.WATER));
}
@Override
public Optional<ItemStack> removeBracket(IBlockReader world, BlockPos pos) {
BracketedTileEntityBehaviour behaviour = TileEntityBehaviour.get(world, pos, BracketedTileEntityBehaviour.TYPE);
if (behaviour == null)
return Optional.empty();
BlockState bracket = behaviour.getBracket();
behaviour.removeBracket();
if (bracket == Blocks.AIR.getDefaultState())
return Optional.empty();
return Optional.of(new ItemStack(bracket.getBlock()));
}
}

View file

@ -1,6 +1,9 @@
package com.simibubi.create.content.contraptions.relays.elementary;
import java.util.List;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.math.AxisAlignedBB;
@ -11,6 +14,12 @@ public class SimpleKineticTileEntity extends KineticTileEntity {
super(type);
}
@Override
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
behaviours.add(new BracketedTileEntityBehaviour(this));
super.addBehaviours(behaviours);
}
@Override
public AxisAlignedBB getRenderBoundingBox() {
return new AxisAlignedBB(pos).grow(1);

View file

@ -1,53 +1,18 @@
package com.simibubi.create.content.contraptions.relays.gauge;
import com.simibubi.create.foundation.data.SpecialBlockStateGen;
import com.simibubi.create.foundation.data.DirectionalAxisBlockStateGen;
import com.tterrag.registrate.providers.DataGenContext;
import com.tterrag.registrate.providers.RegistrateBlockstateProvider;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraftforge.client.model.generators.ModelFile;
public class GaugeGenerator extends SpecialBlockStateGen {
public class GaugeGenerator extends DirectionalAxisBlockStateGen {
@Override
protected int getXRotation(BlockState state) {
Direction direction = state.get(GaugeBlock.FACING);
boolean alongFirst = state.get(GaugeBlock.AXIS_ALONG_FIRST_COORDINATE);
if (direction == Direction.DOWN)
return 180;
if (direction == Direction.UP)
return 0;
if ((direction.getAxis() == Axis.X) == alongFirst)
return 90;
return 0;
}
@Override
protected int getYRotation(BlockState state) {
Direction direction = state.get(GaugeBlock.FACING);
boolean alongFirst = state.get(GaugeBlock.AXIS_ALONG_FIRST_COORDINATE);
if (direction.getAxis()
.isVertical())
return alongFirst ? 90 : 0;
return horizontalAngle(direction) + 90;
}
@Override
public <T extends Block> ModelFile getModel(DataGenContext<Block, T> ctx, RegistrateBlockstateProvider prov,
public <T extends Block> String getModelPrefix(DataGenContext<Block, T> ctx, RegistrateBlockstateProvider prov,
BlockState state) {
boolean vertical = state.get(GaugeBlock.FACING)
.getAxis()
.isVertical();
String partial = vertical ? "base" : "base_wall";
return prov.models()
.getExistingFile(prov.modLoc("block/gauge/" + partial));
return "block/gauge/base";
}
}

View file

@ -0,0 +1,54 @@
package com.simibubi.create.content.contraptions.wrench;
import java.util.Optional;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.fluids.FluidPropagator;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUseContext;
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.math.BlockPos;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.World;
public interface IWrenchableWithBracket extends IWrenchable {
public Optional<ItemStack> removeBracket(IBlockReader world, BlockPos pos);
@Override
default ActionResultType onWrenched(BlockState state, ItemUseContext context) {
if (tryRemoveBracket(context))
return ActionResultType.SUCCESS;
return IWrenchable.super.onWrenched(state, context);
}
default boolean tryRemoveBracket(ItemUseContext context) {
World world = context.getWorld();
BlockPos pos = context.getPos();
Optional<ItemStack> bracket = removeBracket(world, pos);
BlockState blockState = world.getBlockState(pos);
if (bracket.isPresent()) {
PlayerEntity player = context.getPlayer();
if (!world.isRemote && !player.isCreative())
player.inventory.placeItemBackInInventory(world, bracket.get());
if (!world.isRemote && AllBlocks.FLUID_PIPE.has(blockState)) {
Axis preferred = FluidPropagator.getStraightPipeAxis(blockState);
Direction preferredDirection =
preferred == null ? Direction.UP : Direction.getFacingFromAxis(AxisDirection.POSITIVE, preferred);
BlockState updated = AllBlocks.FLUID_PIPE.get()
.updateBlockState(blockState, preferredDirection, null, world, pos);
if (updated != blockState)
world.setBlockState(pos, updated);
}
return true;
}
return false;
}
}

View file

@ -75,20 +75,21 @@ public class BlockzapperItem extends ZapperItem {
@Override
public void fillItemGroup(ItemGroup group, NonNullList<ItemStack> items) {
if (group == Create.baseCreativeTab) {
ItemStack gunWithoutStuff = new ItemStack(this);
items.add(gunWithoutStuff);
if (group != Create.baseCreativeTab && group != ItemGroup.SEARCH)
return;
ItemStack gunWithGoldStuff = new ItemStack(this);
for (Components c : Components.values())
setTier(c, ComponentTier.Brass, gunWithGoldStuff);
items.add(gunWithGoldStuff);
ItemStack gunWithoutStuff = new ItemStack(this);
items.add(gunWithoutStuff);
ItemStack gunWithPurpurStuff = new ItemStack(this);
for (Components c : Components.values())
setTier(c, ComponentTier.Chromatic, gunWithPurpurStuff);
items.add(gunWithPurpurStuff);
}
ItemStack gunWithGoldStuff = new ItemStack(this);
for (Components c : Components.values())
setTier(c, ComponentTier.Brass, gunWithGoldStuff);
items.add(gunWithGoldStuff);
ItemStack gunWithPurpurStuff = new ItemStack(this);
for (Components c : Components.values())
setTier(c, ComponentTier.Chromatic, gunWithPurpurStuff);
items.add(gunWithPurpurStuff);
}
protected boolean activate(World world, PlayerEntity player, ItemStack stack, BlockState selectedState,

View file

@ -234,7 +234,7 @@ public class SchematicHandler {
selectionScreen.cycle((int) delta);
return true;
}
if (!AllKeys.ctrlDown())
if (AllKeys.ctrlDown())
return currentTool.getTool()
.handleMouseWheel(delta);
return false;

View file

@ -12,6 +12,7 @@ public class AllCommands {
//general purpose
.then(ToggleDebugCommand.register())
.then(OverlayConfigCommand.register())
.then(FixLightingCommand.register())
//dev-util
//Comment out for release

View file

@ -10,9 +10,11 @@ import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.gui.ScreenOpener;
import com.simibubi.create.foundation.networking.SimplePacketBase;
import net.minecraft.client.Minecraft;
import net.minecraft.network.PacketBuffer;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.common.ForgeConfig;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.network.NetworkEvent;
@ -39,24 +41,27 @@ public class ConfigureConfigPacket extends SimplePacketBase {
@Override
public void handle(Supplier<NetworkEvent.Context> ctx) {
ctx.get().enqueueWork(() -> DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> {
try {
Actions.valueOf(option).performAction(value);
} catch (IllegalArgumentException e) {
LogManager.getLogger().warn("Received ConfigureConfigPacket with invalid Option: " + option);
}
}));
ctx.get()
.enqueueWork(() -> DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> {
try {
Actions.valueOf(option)
.performAction(value);
} catch (IllegalArgumentException e) {
LogManager.getLogger()
.warn("Received ConfigureConfigPacket with invalid Option: " + option);
}
}));
ctx.get().setPacketHandled(true);
ctx.get()
.setPacketHandled(true);
}
enum Actions {
rainbowDebug((value) -> {
AllConfigs.CLIENT.rainbowDebug.set(Boolean.parseBoolean(value));
}),
overlayScreen((value) -> {
overlayScreenAction();
}),
overlayScreen(Actions::overlayScreenAction),
fixLighting(Actions::experimentalLightingAction),
overlayReset((value) -> {
AllConfigs.CLIENT.overlayOffsetX.set(0);
AllConfigs.CLIENT.overlayOffsetY.set(0);
@ -70,14 +75,19 @@ public class ConfigureConfigPacket extends SimplePacketBase {
this.consumer = action;
}
void performAction(String value){
void performAction(String value) {
consumer.accept(value);
}
@OnlyIn(Dist.CLIENT)
private static void overlayScreenAction(){
//this doesn't work if i move it into the enum constructor like the other two. if there's a proper way to do this, please let me know
private static void overlayScreenAction(String value) {
ScreenOpener.open(new GoggleConfigScreen());
}
@OnlyIn(Dist.CLIENT)
private static void experimentalLightingAction(String value) {
ForgeConfig.CLIENT.experimentalForgeLightPipelineEnabled.set(true);
Minecraft.getInstance().worldRenderer.loadRenderers();
}
}
}

View file

@ -0,0 +1,29 @@
package com.simibubi.create.foundation.command;
import com.mojang.brigadier.builder.ArgumentBuilder;
import com.simibubi.create.foundation.networking.AllPackets;
import net.minecraft.command.CommandSource;
import net.minecraft.command.Commands;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.util.text.StringTextComponent;
import net.minecraftforge.fml.network.PacketDistributor;
public class FixLightingCommand {
static ArgumentBuilder<CommandSource, ?> register() {
return Commands.literal("fixLighting")
.requires(cs -> cs.hasPermissionLevel(0))
.executes(ctx -> {
AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) ctx.getSource()
.getEntity()),
new ConfigureConfigPacket(ConfigureConfigPacket.Actions.fixLighting.name(), String.valueOf(true)));
ctx.getSource()
.sendFeedback(
new StringTextComponent("Forge's experimental block rendering pipeline is now enabled."), true);
return 1;
});
}
}

View file

@ -4,7 +4,12 @@ public class CFluids extends ConfigBase {
public ConfigInt fluidTankCapacity = i(8, 1, "fluidTankCapacity", Comments.buckets, Comments.fluidTankCapacity);
public ConfigInt fluidTankMaxHeight = i(32, 1, "fluidTankMaxHeight", Comments.blocks, Comments.fluidTankMaxHeight);
public ConfigInt mechanicalPumpRange = i(16, 1, "mechanicalPumpRange", Comments.blocks, Comments.mechanicalPumpRange);
public ConfigInt mechanicalPumpRange =
i(16, 1, "mechanicalPumpRange", Comments.blocks, Comments.mechanicalPumpRange);
public ConfigInt hosePulleyBlockThreshold = i(10000, -1, "hosePulleyBlockThreshold", Comments.blocks,
Comments.toDisable, Comments.hosePulleyBlockThreshold);
public ConfigInt hosePulleyRange = i(128, 1, "hosePulleyRange", Comments.blocks, Comments.hosePulleyRange);
@Override
public String getName() {
@ -16,7 +21,13 @@ public class CFluids extends ConfigBase {
static String buckets = "[in Buckets]";
static String fluidTankCapacity = "The amount of liquid a tank can hold per block.";
static String fluidTankMaxHeight = "The maximum height a fluid tank can reach.";
static String mechanicalPumpRange = "The maximum distance a mechanical pump can push or pull liquids on either side.";
static String mechanicalPumpRange =
"The maximum distance a mechanical pump can push or pull liquids on either side.";
static String hosePulleyRange = "The maximum distance a hose pulley can draw fluid blocks from.";
static String toDisable = "[-1 to disable this behaviour]";
static String hosePulleyBlockThreshold =
"The minimum amount of fluid blocks the hose pulley needs to find before deeming it an infinite source.";
}
}

View file

@ -0,0 +1,56 @@
package com.simibubi.create.foundation.data;
import com.simibubi.create.content.contraptions.relays.gauge.GaugeBlock;
import com.tterrag.registrate.providers.DataGenContext;
import com.tterrag.registrate.providers.RegistrateBlockstateProvider;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraftforge.client.model.generators.ModelFile;
public abstract class DirectionalAxisBlockStateGen extends SpecialBlockStateGen {
@Override
protected int getXRotation(BlockState state) {
Direction direction = state.get(GaugeBlock.FACING);
boolean alongFirst = state.get(GaugeBlock.AXIS_ALONG_FIRST_COORDINATE);
if (direction == Direction.DOWN)
return 180;
if (direction == Direction.UP)
return 0;
if ((direction.getAxis() == Axis.X) == alongFirst)
return 90;
return 0;
}
@Override
protected int getYRotation(BlockState state) {
Direction direction = state.get(GaugeBlock.FACING);
boolean alongFirst = state.get(GaugeBlock.AXIS_ALONG_FIRST_COORDINATE);
if (direction.getAxis()
.isVertical())
return alongFirst ? 90 : 0;
return horizontalAngle(direction) + 90;
}
public abstract <T extends Block> String getModelPrefix(DataGenContext<Block, T> ctx,
RegistrateBlockstateProvider prov, BlockState state);
@Override
public <T extends Block> ModelFile getModel(DataGenContext<Block, T> ctx, RegistrateBlockstateProvider prov,
BlockState state) {
boolean vertical = state.get(GaugeBlock.FACING)
.getAxis()
.isVertical();
String partial = vertical ? "" : "_wall";
return prov.models()
.getExistingFile(prov.modLoc(getModelPrefix(ctx, prov, state) + partial));
}
}

View file

@ -14,6 +14,7 @@ import net.minecraft.data.IFinishedRecipe;
import net.minecraft.data.RecipeProvider;
import net.minecraft.item.Item;
import net.minecraft.tags.ITag;
import net.minecraft.tags.ItemTags;
import net.minecraft.util.IItemProvider;
import net.minecraftforge.common.Tags;
@ -50,6 +51,10 @@ public abstract class CreateRecipeProvider extends RecipeProvider {
return Tags.Items.DUSTS_REDSTONE;
}
static ITag.INamedTag<Item> planks() {
return ItemTags.PLANKS;
}
static ITag.INamedTag<Item> gold() {
return AllTags.forgeItemTag("ingots/gold");
}

View file

@ -422,6 +422,22 @@ public class StandardRecipeGen extends CreateRecipeProvider {
.patternLine("SCS")
.patternLine(" I ")),
WOODEN_BRACKET = create(AllBlocks.WOODEN_BRACKET).returns(4)
.unlockedBy(I::andesite)
.viaShaped(b -> b.key('S', Tags.Items.RODS_WOODEN)
.key('P', I.planks())
.key('C', I.andesite())
.patternLine("SSS")
.patternLine("PCP")),
METAL_BRACKET = create(AllBlocks.METAL_BRACKET).returns(4)
.unlockedBy(I::andesite)
.viaShaped(b -> b.key('S', Tags.Items.NUGGETS_IRON)
.key('P', I.iron())
.key('C', I.andesite())
.patternLine("SSS")
.patternLine("PCP")),
FLUID_PIPE = create(AllBlocks.FLUID_PIPE).returns(16)
.unlockedByTag(I::copper)
.viaShaped(b -> b.key('S', I.copperSheet())
@ -459,8 +475,7 @@ public class StandardRecipeGen extends CreateRecipeProvider {
.patternLine("S")),
ITEM_DRAIN = create(AllBlocks.ITEM_DRAIN).unlockedBy(I::copperCasing)
.viaShaped(b -> b
.key('P', Blocks.IRON_BARS)
.viaShaped(b -> b.key('P', Blocks.IRON_BARS)
.key('S', I.copperCasing())
.patternLine("P")
.patternLine("S")),
@ -499,8 +514,7 @@ public class StandardRecipeGen extends CreateRecipeProvider {
.patternLine(" I ")),
HOSE_PULLEY = create(AllBlocks.HOSE_PULLEY).unlockedByTag(I::copper)
.viaShaped(b -> b
.key('S', I.shaft())
.viaShaped(b -> b.key('S', I.shaft())
.key('P', AllBlocks.FLUID_PIPE.get())
.key('B', I.copperCasing())
.key('C', Items.DRIED_KELP)

View file

@ -12,6 +12,8 @@ import com.simibubi.create.content.contraptions.processing.EmptyingByBasin;
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
import com.simibubi.create.foundation.utility.Pair;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.fluid.Fluid;
import net.minecraft.fluid.Fluids;
@ -44,6 +46,11 @@ public class FluidHelper {
return convertToStill(fluid) == Fluids.LAVA;
}
public static boolean hasBlockState(Fluid fluid) {
BlockState blockState = fluid.getDefaultState().getBlockState();
return blockState != null && blockState != Blocks.AIR.getDefaultState();
}
public static Fluid convertToFlowing(Fluid fluid) {
if (fluid == Fluids.WATER)
return Fluids.FLOWING_WATER;

View file

@ -1,5 +1,6 @@
package com.simibubi.create.foundation.fluid;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
@ -13,8 +14,8 @@ import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException;
import com.simibubi.create.foundation.data.NamedTag;
import net.minecraft.fluid.FlowingFluid;
import net.minecraft.fluid.Fluid;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.network.PacketBuffer;
@ -182,7 +183,8 @@ public abstract class FluidIngredient implements Predicate<FluidStack> {
@Override
protected List<FluidStack> determineMatchingFluidStacks() {
return ImmutableList.of(new FluidStack(fluid, amountRequired, tagToMatch));
return ImmutableList.of(tagToMatch.isEmpty() ? new FluidStack(fluid, amountRequired)
: new FluidStack(fluid, amountRequired, tagToMatch));
}
}
@ -193,20 +195,30 @@ public abstract class FluidIngredient implements Predicate<FluidStack> {
@Override
protected boolean testInternal(FluidStack t) {
if (tag == null)
for (FluidStack accepted : getMatchingFluidStacks())
if (accepted.getFluid()
.isEquivalentTo(t.getFluid()))
return true;
return t.getFluid()
.isIn(tag);
}
@Override
protected void readInternal(PacketBuffer buffer) {
ResourceLocation resourcelocation = buffer.readResourceLocation();
tag = new NamedTag<>(FluidTags.func_226157_a_()
.get(resourcelocation), resourcelocation);
int size = buffer.readVarInt();
matchingFluidStacks = new ArrayList<>(size);
for (int i = 0; i < size; i++)
matchingFluidStacks.add(buffer.readFluidStack());
}
@Override
protected void writeInternal(PacketBuffer buffer) {
buffer.writeResourceLocation(tag.getId());
// Tag has to be resolved on the server before sending
List<FluidStack> matchingFluidStacks = getMatchingFluidStacks();
buffer.writeVarInt(matchingFluidStacks.size());
matchingFluidStacks.stream()
.forEach(buffer::writeFluidStack);
}
@Override
@ -232,6 +244,12 @@ public abstract class FluidIngredient implements Predicate<FluidStack> {
protected List<FluidStack> determineMatchingFluidStacks() {
return tag.values()
.stream()
.map(f -> {
if (f instanceof FlowingFluid)
return ((FlowingFluid) f).getStillFluid();
return f;
})
.distinct()
.map(f -> new FluidStack(f, amountRequired))
.collect(Collectors.toList());
}

View file

@ -12,6 +12,7 @@ import com.simibubi.create.AllBlockPartials;
import com.simibubi.create.foundation.fluid.FluidRenderer;
import com.simibubi.create.foundation.utility.ColorHelper;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.foundation.utility.VirtualEmptyModelData;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
@ -205,7 +206,7 @@ public class GuiGameElement {
Vector3d rgb = ColorHelper.getRGB(color);
blockRenderer.getBlockModelRenderer()
.renderModel(ms.peek(), vb, blockState, blockmodel, (float) rgb.x, (float) rgb.y, (float) rgb.z,
0xF000F0, OverlayTexture.DEFAULT_UV, EmptyModelData.INSTANCE);
0xF000F0, OverlayTexture.DEFAULT_UV, VirtualEmptyModelData.INSTANCE);
buffer.draw();
}
}
@ -224,7 +225,7 @@ public class GuiGameElement {
if (blockState.getBlock() instanceof FireBlock) {
RenderHelper.disableGuiDepthLighting();
blockRenderer.renderBlock(blockState, ms, buffer, 0xF000F0, OverlayTexture.DEFAULT_UV,
EmptyModelData.INSTANCE);
VirtualEmptyModelData.INSTANCE);
RenderHelper.enable();
buffer.draw();
return;

View file

@ -268,6 +268,16 @@ public class SmartFluidTankBehaviour extends TileEntityBehaviour {
renderedFluid = tank.getFluid();
}
public boolean isEmpty(float partialTicks) {
FluidStack renderedFluid = getRenderedFluid();
if (renderedFluid.isEmpty())
return true;
float units = getTotalUnits(partialTicks);
if (units < 1)
return true;
return false;
}
}
@Override

View file

@ -1,5 +1,6 @@
package com.simibubi.create.foundation.utility;
import java.util.Iterator;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
@ -12,7 +13,7 @@ import com.google.common.collect.ImmutableList;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.ListNBT;
public class Couple<T> extends Pair<T, T> {
public class Couple<T> extends Pair<T, T> implements Iterable<T> {
private static Couple<Boolean> TRUE_AND_FALSE = Couple.create(true, false);
@ -62,7 +63,8 @@ public class Couple<T> extends Pair<T, T> {
setSecond(function.apply(getSecond(), values.getSecond()));
}
public void forEach(Consumer<T> consumer) {
@Override
public void forEach(Consumer<? super T> consumer) {
consumer.accept(getFirst());
consumer.accept(getSecond());
}
@ -89,4 +91,36 @@ public class Couple<T> extends Pair<T, T> {
return new Couple<>(readCompoundList.get(0), readCompoundList.get(1));
}
@Override
public Iterator<T> iterator() {
return new Couplerator<>(this);
}
private static class Couplerator<T> implements Iterator<T> {
int state;
private Couple<T> couple;
public Couplerator(Couple<T> couple) {
this.couple = couple;
state = 0;
}
@Override
public boolean hasNext() {
return state != 2;
}
@Override
public T next() {
state++;
if (state == 1)
return couple.first;
if (state == 2)
return couple.second;
return null;
}
}
}

View file

@ -0,0 +1,37 @@
package com.simibubi.create.foundation.utility;
public class IntAttached<V> extends Pair<Integer, V> {
protected IntAttached(Integer first, V second) {
super(first, second);
}
public static <V> IntAttached<V> with(int number, V value) {
return new IntAttached<>(number, value);
}
public static <V> IntAttached<V> withZero(V value) {
return new IntAttached<>(0, value);
}
public boolean isZero() {
return first.intValue() == 0;
}
public boolean isOrBelowZero() {
return first.intValue() <= 0;
}
public void increment() {
first++;
}
public void decrement() {
first--;
}
public V getValue() {
return getSecond();
}
}

View file

@ -24,7 +24,6 @@ import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.client.model.data.EmptyModelData;
public class SuperByteBufferCache {
@ -116,7 +115,7 @@ public class SuperByteBufferCache {
builder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK);
blockRenderer.renderModel(mc.world, model, referenceState, BlockPos.ZERO.up(255), ms, builder, true,
mc.world.rand, 42, OverlayTexture.DEFAULT_UV, EmptyModelData.INSTANCE);
mc.world.rand, 42, OverlayTexture.DEFAULT_UV, VirtualEmptyModelData.INSTANCE);
builder.finishDrawing();
return new SuperByteBuffer(builder);

View file

@ -0,0 +1,30 @@
package com.simibubi.create.foundation.utility;
import net.minecraftforge.client.model.data.IModelData;
import net.minecraftforge.client.model.data.ModelProperty;
/**
* This model data instance is passed whenever a model is rendered without
* available in-world context. IBakedModel#getModelData can react accordingly
* and avoid looking for model data itself
**/
public enum VirtualEmptyModelData implements IModelData {
INSTANCE;
@Override
public boolean hasProperty(ModelProperty<?> prop) {
return false;
}
@Override
public <T> T getData(ModelProperty<T> prop) {
return null;
}
@Override
public <T> T setData(ModelProperty<T> prop, T data) {
return null;
}
}

View file

@ -123,23 +123,10 @@
"up": {"uv": [6, 0, 8, 6], "rotation": 90, "texture": "#3"}
}
},
{
"name": "BackBottom",
"from": [3.9, -2, 18],
"to": [12.1, 2, 26],
"rotation": {"angle": -22.5, "axis": "x", "origin": [8, -4, 17]},
"faces": {
"east": {"uv": [12, 12, 14, 16], "rotation": 270, "texture": "#7"},
"south": {"uv": [8, 13, 12, 15], "rotation": 180, "texture": "#7"},
"west": {"uv": [12, 12, 14, 16], "rotation": 270, "texture": "#7"},
"up": {"uv": [8, 12, 12, 16], "rotation": 180, "texture": "#7"},
"down": {"uv": [8, 12, 12, 16], "rotation": 180, "texture": "#7"}
}
},
{
"name": "Back",
"from": [2.1, -2.1, 14],
"to": [13.9, 13.9, 17.9],
"to": [13.9, 13.95, 18.1],
"rotation": {"angle": 0, "axis": "y", "origin": [8, -8, 6]},
"faces": {
"north": {"uv": [0, 4, 16, 16], "rotation": 90, "texture": "#5"},
@ -204,7 +191,7 @@
{
"name": "Base",
"origin": [9, -4, 8],
"children": [9, 10, 11, 12, 13]
"children": [9, 10, 11, 12]
}
]
}

View file

@ -108,23 +108,10 @@
"down": {"uv": [0, 0, 1, 6], "texture": "#particle"}
}
},
{
"name": "BackBottom",
"from": [3.9, -2, 18],
"to": [12.1, 2, 26],
"rotation": {"angle": -22.5, "axis": "x", "origin": [8, -4, 17]},
"faces": {
"east": {"uv": [12, 12, 14, 16], "rotation": 270, "texture": "#7"},
"south": {"uv": [8, 13, 12, 15], "rotation": 180, "texture": "#7"},
"west": {"uv": [12, 12, 14, 16], "rotation": 270, "texture": "#7"},
"up": {"uv": [8, 12, 12, 16], "rotation": 180, "texture": "#7"},
"down": {"uv": [8, 12, 12, 16], "rotation": 180, "texture": "#7"}
}
},
{
"name": "Back",
"from": [2.1, -2.1, 14],
"to": [13.9, 13.9, 17.9],
"to": [13.9, 13.95, 18.1],
"rotation": {"angle": 0, "axis": "y", "origin": [8, -8.1, 6]},
"faces": {
"east": {"uv": [0, 0, 16, 4], "rotation": 90, "texture": "#5"},
@ -196,8 +183,8 @@
{
"name": "Base",
"origin": [9, -4, 8],
"children": [8, 9, 10, 11, 12]
"children": [8, 9, 10, 11]
}
]
}, 13]
}, 12]
}

View file

@ -0,0 +1,208 @@
{
"credit": "Made with Blockbench",
"parent": "block/block",
"textures": {
"4": "#plate",
"5": "#bracket"
},
"elements": [
{
"from": [11.9, 3, 2],
"to": [14, 6, 6],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 4.5, -24]},
"faces": {
"north": {"uv": [8, 3, 10, 6], "texture": "#5"},
"east": {"uv": [10, 3, 14, 6], "texture": "#5"},
"south": {"uv": [10, 3, 8, 6], "texture": "#5"},
"up": {"uv": [10, 1, 14, 3], "rotation": 90, "texture": "#5"},
"down": {"uv": [10, 1, 14, 3], "rotation": 90, "texture": "#5"}
}
},
{
"from": [4.1, 3, 2],
"to": [11.9, 13, 6],
"rotation": {"angle": 0, "axis": "y", "origin": [10, 4.5, -24]},
"faces": {
"north": {"uv": [0, 0, 8, 10], "rotation": 180, "texture": "#5"},
"east": {"uv": [7, 0, 8, 10], "texture": "#5"},
"south": {"uv": [0, 0, 8, 10], "rotation": 180, "texture": "#5"},
"west": {"uv": [7, 0, 8, 10], "texture": "#5"},
"up": {"uv": [8, 6, 16, 10], "texture": "#5"}
}
},
{
"from": [2, 3, 2],
"to": [4.1, 6, 6],
"rotation": {"angle": 0, "axis": "y", "origin": [3, 4.5, -24]},
"faces": {
"north": {"uv": [10, 3, 8, 6], "texture": "#5"},
"south": {"uv": [8, 3, 10, 6], "texture": "#5"},
"west": {"uv": [10, 3, 14, 6], "texture": "#5"},
"up": {"uv": [10, 1, 14, 3], "rotation": 270, "texture": "#5"},
"down": {"uv": [10, 1, 14, 3], "rotation": 270, "texture": "#5"}
}
},
{
"from": [2, 10, 2],
"to": [4.1, 13, 6],
"rotation": {"angle": 0, "axis": "y", "origin": [3, 11.5, -24]},
"faces": {
"north": {"uv": [10, 3, 8, 6], "texture": "#5"},
"south": {"uv": [8, 3, 10, 6], "texture": "#5"},
"west": {"uv": [10, 3, 14, 6], "texture": "#5"},
"up": {"uv": [10, 1, 14, 3], "rotation": 270, "texture": "#5"},
"down": {"uv": [10, 1, 14, 3], "rotation": 270, "texture": "#5"}
}
},
{
"from": [12.5, 6, 3.5],
"to": [13.5, 14, 4.5],
"rotation": {"angle": 0, "axis": "y", "origin": [20, 14, -16]},
"faces": {
"north": {"uv": [15, 8, 16, 16], "texture": "#4"},
"east": {"uv": [14, 8, 15, 16], "texture": "#4"},
"south": {"uv": [15, 8, 16, 16], "texture": "#4"},
"west": {"uv": [15, 8, 16, 16], "texture": "#4"},
"up": {"uv": [14, 7, 15, 8], "texture": "#4"},
"down": {"uv": [0, 0, 0, 0], "texture": "#4"}
}
},
{
"from": [11.9, 10, 2],
"to": [14, 13, 6],
"rotation": {"angle": 0, "axis": "y", "origin": [18, 11.5, -24]},
"faces": {
"north": {"uv": [8, 3, 10, 6], "texture": "#5"},
"east": {"uv": [10, 3, 14, 6], "texture": "#5"},
"south": {"uv": [10, 3, 8, 6], "texture": "#5"},
"up": {"uv": [10, 1, 14, 3], "rotation": 90, "texture": "#5"},
"down": {"uv": [10, 1, 14, 3], "rotation": 90, "texture": "#5"}
}
},
{
"from": [2.5, 6, 3.5],
"to": [3.5, 14, 4.5],
"rotation": {"angle": 0, "axis": "y", "origin": [10, 14, -16]},
"faces": {
"north": {"uv": [15, 8, 16, 16], "texture": "#4"},
"east": {"uv": [14, 8, 15, 16], "texture": "#4"},
"south": {"uv": [15, 8, 16, 16], "texture": "#4"},
"west": {"uv": [15, 8, 16, 16], "texture": "#4"},
"up": {"uv": [14, 7, 15, 8], "texture": "#4"},
"down": {"uv": [0, 0, 0, 0], "texture": "#4"}
}
},
{
"from": [11.9, 3, 10],
"to": [14, 6, 14],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 4.5, -16]},
"faces": {
"north": {"uv": [8, 3, 10, 6], "texture": "#5"},
"east": {"uv": [10, 3, 14, 6], "texture": "#5"},
"south": {"uv": [10, 3, 8, 6], "texture": "#5"},
"up": {"uv": [10, 1, 14, 3], "rotation": 90, "texture": "#5"},
"down": {"uv": [10, 1, 14, 3], "rotation": 90, "texture": "#5"}
}
},
{
"from": [4.1, 3, 10],
"to": [11.9, 13, 14],
"rotation": {"angle": 0, "axis": "y", "origin": [10, 4.5, -16]},
"faces": {
"north": {"uv": [0, 0, 8, 10], "rotation": 180, "texture": "#5"},
"east": {"uv": [7, 0, 8, 10], "texture": "#5"},
"south": {"uv": [0, 0, 8, 10], "rotation": 180, "texture": "#5"},
"west": {"uv": [7, 0, 8, 10], "texture": "#5"},
"up": {"uv": [8, 6, 16, 10], "texture": "#5"}
}
},
{
"from": [2, 3, 10],
"to": [4.1, 6, 14],
"rotation": {"angle": 0, "axis": "y", "origin": [3, 4.5, -16]},
"faces": {
"north": {"uv": [10, 3, 8, 6], "texture": "#5"},
"south": {"uv": [8, 3, 10, 6], "texture": "#5"},
"west": {"uv": [10, 3, 14, 6], "texture": "#5"},
"up": {"uv": [10, 1, 14, 3], "rotation": 270, "texture": "#5"},
"down": {"uv": [10, 1, 14, 3], "rotation": 270, "texture": "#5"}
}
},
{
"from": [2, 10, 10],
"to": [4.1, 13, 14],
"rotation": {"angle": 0, "axis": "y", "origin": [3, 11.5, -16]},
"faces": {
"north": {"uv": [10, 3, 8, 6], "texture": "#5"},
"south": {"uv": [8, 3, 10, 6], "texture": "#5"},
"west": {"uv": [10, 3, 14, 6], "texture": "#5"},
"up": {"uv": [10, 1, 14, 3], "rotation": 270, "texture": "#5"},
"down": {"uv": [10, 1, 14, 3], "rotation": 270, "texture": "#5"}
}
},
{
"from": [12.5, 6, 11.5],
"to": [13.5, 14, 12.5],
"rotation": {"angle": 0, "axis": "y", "origin": [20, 14, -8]},
"faces": {
"north": {"uv": [15, 8, 16, 16], "texture": "#4"},
"east": {"uv": [14, 8, 15, 16], "texture": "#4"},
"south": {"uv": [15, 8, 16, 16], "texture": "#4"},
"west": {"uv": [15, 8, 16, 16], "texture": "#4"},
"up": {"uv": [14, 7, 15, 8], "texture": "#4"},
"down": {"uv": [0, 0, 0, 0], "texture": "#4"}
}
},
{
"from": [11.9, 10, 10],
"to": [14, 13, 14],
"rotation": {"angle": 0, "axis": "y", "origin": [18, 11.5, -16]},
"faces": {
"north": {"uv": [8, 3, 10, 6], "texture": "#5"},
"east": {"uv": [10, 3, 14, 6], "texture": "#5"},
"south": {"uv": [10, 3, 8, 6], "texture": "#5"},
"up": {"uv": [10, 1, 14, 3], "rotation": 90, "texture": "#5"},
"down": {"uv": [10, 1, 14, 3], "rotation": 90, "texture": "#5"}
}
},
{
"from": [2.5, 6, 11.5],
"to": [3.5, 14, 12.5],
"rotation": {"angle": 0, "axis": "y", "origin": [10, 14, -8]},
"faces": {
"north": {"uv": [15, 8, 16, 16], "texture": "#4"},
"east": {"uv": [14, 8, 15, 16], "texture": "#4"},
"south": {"uv": [15, 8, 16, 16], "texture": "#4"},
"west": {"uv": [15, 8, 16, 16], "texture": "#4"},
"up": {"uv": [14, 7, 15, 8], "texture": "#4"},
"down": {"uv": [0, 0, 0, 0], "texture": "#4"}
}
},
{
"from": [1, 0, 1],
"to": [15, 3, 6],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 1.5, 8]},
"faces": {
"north": {"uv": [0, 10, 14, 13], "texture": "#5"},
"east": {"uv": [0, 13, 5, 16], "rotation": 180, "texture": "#5"},
"south": {"uv": [0, 10, 14, 13], "texture": "#5"},
"west": {"uv": [0, 13, 5, 16], "texture": "#5"},
"up": {"uv": [9, 2, 14, 16], "rotation": 90, "texture": "#4"},
"down": {"uv": [9, 2, 14, 16], "rotation": 90, "texture": "#4"}
}
},
{
"from": [1, 0, 10],
"to": [15, 3, 15],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 1.5, 8]},
"faces": {
"north": {"uv": [0, 10, 14, 13], "texture": "#5"},
"east": {"uv": [0, 13, 5, 16], "texture": "#5"},
"south": {"uv": [0, 10, 14, 13], "texture": "#5"},
"west": {"uv": [0, 13, 5, 16], "rotation": 180, "texture": "#5"},
"up": {"uv": [9, 2, 14, 16], "rotation": 270, "texture": "#4"},
"down": {"uv": [9, 2, 14, 16], "rotation": 270, "texture": "#4"}
}
}
]
}

View file

@ -0,0 +1,206 @@
{
"credit": "Made with Blockbench",
"parent": "block/block",
"texture_size": [32, 32],
"textures": {
"4": "#plate",
"5": "#bracket",
"particle": "#plate"
},
"elements": [
{
"from": [3, 2, 2],
"to": [6, 4.1, 6],
"faces": {
"north": {"uv": [8, 3, 10, 6], "rotation": 270, "texture": "#5"},
"east": {"uv": [10, 1, 14, 3], "rotation": 180, "texture": "#5"},
"south": {"uv": [10, 3, 8, 6], "rotation": 90, "texture": "#5"},
"west": {"uv": [10, 1, 14, 3], "rotation": 180, "texture": "#5"},
"down": {"uv": [10, 3, 14, 6], "rotation": 90, "texture": "#5"}
}
},
{
"from": [3, 4.1, 2],
"to": [13, 11.9, 6],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 6, 8]},
"faces": {
"north": {"uv": [0, 0, 8, 10], "rotation": 90, "texture": "#5"},
"east": {"uv": [8, 6, 16, 10], "rotation": 90, "texture": "#5"},
"south": {"uv": [0, 0, 8, 10], "rotation": 270, "texture": "#5"},
"up": {"uv": [7, 0, 8, 10], "rotation": 90, "texture": "#5"},
"down": {"uv": [7, 0, 8, 10], "rotation": 90, "texture": "#5"}
}
},
{
"from": [3, 11.9, 2],
"to": [6, 14, 6],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 13, 8]},
"faces": {
"north": {"uv": [10, 3, 8, 6], "rotation": 270, "texture": "#5"},
"east": {"uv": [10, 1, 14, 3], "texture": "#5"},
"south": {"uv": [8, 3, 10, 6], "rotation": 90, "texture": "#5"},
"west": {"uv": [10, 1, 14, 3], "texture": "#5"},
"up": {"uv": [10, 3, 14, 6], "rotation": 90, "texture": "#5"}
}
},
{
"from": [10, 11.9, 2],
"to": [13, 14, 6],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 13, 8]},
"faces": {
"north": {"uv": [10, 3, 8, 6], "rotation": 270, "texture": "#5"},
"east": {"uv": [10, 1, 14, 3], "texture": "#5"},
"south": {"uv": [8, 3, 10, 6], "rotation": 90, "texture": "#5"},
"west": {"uv": [10, 1, 14, 3], "texture": "#5"},
"up": {"uv": [10, 3, 14, 6], "rotation": 90, "texture": "#5"}
}
},
{
"from": [6, 2.5, 3.5],
"to": [14, 3.5, 4.5],
"rotation": {"angle": 0, "axis": "y", "origin": [8, -4, 8]},
"faces": {
"north": {"uv": [15, 8, 16, 16], "rotation": 270, "texture": "#4"},
"east": {"uv": [14, 7, 15, 8], "rotation": 90, "texture": "#4"},
"south": {"uv": [15, 8, 16, 16], "rotation": 90, "texture": "#4"},
"west": {"uv": [0, 0, 0, 0], "rotation": 90, "texture": "#4"},
"up": {"uv": [15, 8, 16, 16], "rotation": 90, "texture": "#4"},
"down": {"uv": [14, 8, 15, 16], "rotation": 90, "texture": "#4"}
}
},
{
"from": [10, 2, 2],
"to": [13, 4.1, 6],
"rotation": {"angle": 0, "axis": "y", "origin": [8, -2, 8]},
"faces": {
"north": {"uv": [8, 3, 10, 6], "rotation": 270, "texture": "#5"},
"east": {"uv": [10, 1, 14, 3], "rotation": 180, "texture": "#5"},
"south": {"uv": [10, 3, 8, 6], "rotation": 90, "texture": "#5"},
"west": {"uv": [10, 1, 14, 3], "rotation": 180, "texture": "#5"},
"down": {"uv": [10, 3, 14, 6], "rotation": 90, "texture": "#5"}
}
},
{
"from": [6, 12.5, 3.5],
"to": [14, 13.5, 4.5],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 6, 8]},
"faces": {
"north": {"uv": [15, 8, 16, 16], "rotation": 270, "texture": "#4"},
"east": {"uv": [14, 7, 15, 8], "rotation": 90, "texture": "#4"},
"south": {"uv": [15, 8, 16, 16], "rotation": 90, "texture": "#4"},
"west": {"uv": [0, 0, 0, 0], "rotation": 90, "texture": "#4"},
"up": {"uv": [15, 8, 16, 16], "rotation": 90, "texture": "#4"},
"down": {"uv": [14, 8, 15, 16], "rotation": 90, "texture": "#4"}
}
},
{
"from": [3, 2, 10],
"to": [6, 4.1, 14],
"faces": {
"north": {"uv": [8, 3, 10, 6], "rotation": 270, "texture": "#5"},
"east": {"uv": [10, 1, 14, 3], "rotation": 180, "texture": "#5"},
"south": {"uv": [10, 3, 8, 6], "rotation": 90, "texture": "#5"},
"west": {"uv": [10, 1, 14, 3], "rotation": 180, "texture": "#5"},
"down": {"uv": [10, 3, 14, 6], "rotation": 90, "texture": "#5"}
}
},
{
"from": [3, 4.1, 10],
"to": [13, 11.9, 14],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 6, 8]},
"faces": {
"north": {"uv": [0, 0, 8, 10], "rotation": 90, "texture": "#5"},
"east": {"uv": [8, 6, 16, 10], "rotation": 90, "texture": "#5"},
"south": {"uv": [0, 0, 8, 10], "rotation": 270, "texture": "#5"},
"up": {"uv": [7, 0, 8, 10], "rotation": 90, "texture": "#5"},
"down": {"uv": [7, 0, 8, 10], "rotation": 90, "texture": "#5"}
}
},
{
"from": [3, 11.9, 10],
"to": [6, 14, 14],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 13, 8]},
"faces": {
"north": {"uv": [10, 3, 8, 6], "rotation": 270, "texture": "#5"},
"east": {"uv": [10, 1, 14, 3], "texture": "#5"},
"south": {"uv": [8, 3, 10, 6], "rotation": 90, "texture": "#5"},
"west": {"uv": [10, 1, 14, 3], "texture": "#5"},
"up": {"uv": [10, 3, 14, 6], "rotation": 90, "texture": "#5"}
}
},
{
"from": [10, 11.9, 10],
"to": [13, 14, 14],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 13, 8]},
"faces": {
"north": {"uv": [10, 3, 8, 6], "rotation": 270, "texture": "#5"},
"east": {"uv": [10, 1, 14, 3], "texture": "#5"},
"south": {"uv": [8, 3, 10, 6], "rotation": 90, "texture": "#5"},
"west": {"uv": [10, 1, 14, 3], "texture": "#5"},
"up": {"uv": [10, 3, 14, 6], "rotation": 90, "texture": "#5"}
}
},
{
"from": [6, 2.5, 11.5],
"to": [14, 3.5, 12.5],
"rotation": {"angle": 0, "axis": "y", "origin": [8, -4, 8]},
"faces": {
"north": {"uv": [15, 8, 16, 16], "rotation": 270, "texture": "#4"},
"east": {"uv": [14, 7, 15, 8], "rotation": 90, "texture": "#4"},
"south": {"uv": [15, 8, 16, 16], "rotation": 90, "texture": "#4"},
"west": {"uv": [0, 0, 0, 0], "rotation": 90, "texture": "#4"},
"up": {"uv": [15, 8, 16, 16], "rotation": 90, "texture": "#4"},
"down": {"uv": [14, 8, 15, 16], "rotation": 90, "texture": "#4"}
}
},
{
"from": [10, 2, 10],
"to": [13, 4.1, 14],
"rotation": {"angle": 0, "axis": "y", "origin": [8, -2, 8]},
"faces": {
"north": {"uv": [8, 3, 10, 6], "rotation": 270, "texture": "#5"},
"east": {"uv": [10, 1, 14, 3], "rotation": 180, "texture": "#5"},
"south": {"uv": [10, 3, 8, 6], "rotation": 90, "texture": "#5"},
"west": {"uv": [10, 1, 14, 3], "rotation": 180, "texture": "#5"},
"down": {"uv": [10, 3, 14, 6], "rotation": 90, "texture": "#5"}
}
},
{
"from": [6, 12.5, 11.5],
"to": [14, 13.5, 12.5],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 6, 8]},
"faces": {
"north": {"uv": [15, 8, 16, 16], "rotation": 270, "texture": "#4"},
"east": {"uv": [14, 7, 15, 8], "rotation": 90, "texture": "#4"},
"south": {"uv": [15, 8, 16, 16], "rotation": 90, "texture": "#4"},
"west": {"uv": [0, 0, 0, 0], "rotation": 90, "texture": "#4"},
"up": {"uv": [15, 8, 16, 16], "rotation": 90, "texture": "#4"},
"down": {"uv": [14, 8, 15, 16], "rotation": 90, "texture": "#4"}
}
},
{
"from": [0, 1, 1],
"to": [3, 15, 6],
"faces": {
"north": {"uv": [0, 10, 14, 13], "rotation": 270, "texture": "#5"},
"east": {"uv": [9, 2, 14, 16], "rotation": 180, "texture": "#4"},
"south": {"uv": [0, 10, 14, 13], "rotation": 90, "texture": "#5"},
"west": {"uv": [9, 2, 14, 16], "rotation": 180, "texture": "#4"},
"up": {"uv": [0, 13, 5, 16], "rotation": 90, "texture": "#5"},
"down": {"uv": [0, 13, 5, 16], "rotation": 270, "texture": "#5"}
}
},
{
"from": [0, 1, 10],
"to": [3, 15, 15],
"faces": {
"north": {"uv": [0, 10, 14, 13], "rotation": 270, "texture": "#5"},
"east": {"uv": [9, 2, 14, 16], "texture": "#4"},
"south": {"uv": [0, 10, 14, 13], "rotation": 90, "texture": "#5"},
"west": {"uv": [9, 2, 14, 16], "texture": "#4"},
"up": {"uv": [0, 13, 5, 16], "rotation": 270, "texture": "#5"},
"down": {"uv": [0, 13, 5, 16], "rotation": 90, "texture": "#5"}
}
}
]
}

View file

@ -0,0 +1,110 @@
{
"credit": "Made with Blockbench",
"parent": "block/block",
"textures": {
"4": "#plate",
"5": "#bracket",
"particle": "#plate"
},
"elements": [
{
"from": [1, 0, 1],
"to": [15, 3, 15],
"rotation": {"angle": 0, "axis": "y", "origin": [1.5, 0, 1.5]},
"faces": {
"north": {"uv": [0, 10, 14, 13], "texture": "#5"},
"east": {"uv": [0, 13, 14, 16], "texture": "#5"},
"south": {"uv": [0, 10, 14, 13], "texture": "#5"},
"west": {"uv": [0, 13, 14, 16], "texture": "#5"},
"up": {"uv": [0, 2, 14, 16], "rotation": 90, "texture": "#4"},
"down": {"uv": [0, 2, 14, 16], "rotation": 270, "texture": "#4"}
}
},
{
"from": [11.9, 3, 6],
"to": [14, 6, 10],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 4.5, 8]},
"faces": {
"north": {"uv": [8, 3, 10, 6], "texture": "#5"},
"east": {"uv": [10, 3, 14, 6], "texture": "#5"},
"south": {"uv": [10, 3, 8, 6], "texture": "#5"},
"up": {"uv": [10, 1, 14, 3], "rotation": 90, "texture": "#5"},
"down": {"uv": [10, 1, 14, 3], "rotation": 90, "texture": "#5"}
}
},
{
"from": [4.1, 3, 6],
"to": [11.9, 13, 10],
"rotation": {"angle": 0, "axis": "y", "origin": [10, 4.5, 8]},
"faces": {
"north": {"uv": [0, 0, 8, 10], "rotation": 180, "texture": "#5"},
"east": {"uv": [7, 0, 8, 10], "texture": "#5"},
"south": {"uv": [0, 0, 8, 10], "rotation": 180, "texture": "#5"},
"west": {"uv": [7, 0, 8, 10], "texture": "#5"},
"up": {"uv": [8, 6, 16, 10], "texture": "#5"}
}
},
{
"from": [2, 3, 6],
"to": [4.1, 6, 10],
"rotation": {"angle": 0, "axis": "y", "origin": [3, 4.5, 8]},
"faces": {
"north": {"uv": [10, 3, 8, 6], "texture": "#5"},
"south": {"uv": [8, 3, 10, 6], "texture": "#5"},
"west": {"uv": [10, 3, 14, 6], "texture": "#5"},
"up": {"uv": [10, 1, 14, 3], "rotation": 270, "texture": "#5"},
"down": {"uv": [10, 1, 14, 3], "rotation": 270, "texture": "#5"}
}
},
{
"from": [2, 10, 6],
"to": [4.1, 13, 10],
"rotation": {"angle": 0, "axis": "y", "origin": [3, 11.5, 8]},
"faces": {
"north": {"uv": [10, 3, 8, 6], "texture": "#5"},
"south": {"uv": [8, 3, 10, 6], "texture": "#5"},
"west": {"uv": [10, 3, 14, 6], "texture": "#5"},
"up": {"uv": [10, 1, 14, 3], "rotation": 270, "texture": "#5"},
"down": {"uv": [10, 1, 14, 3], "rotation": 270, "texture": "#5"}
}
},
{
"from": [12.5, 6, 7.5],
"to": [13.5, 14, 8.5],
"rotation": {"angle": 0, "axis": "y", "origin": [20, 14, 16]},
"faces": {
"north": {"uv": [15, 8, 16, 16], "texture": "#4"},
"east": {"uv": [14, 8, 15, 16], "texture": "#4"},
"south": {"uv": [15, 8, 16, 16], "texture": "#4"},
"west": {"uv": [15, 8, 16, 16], "texture": "#4"},
"up": {"uv": [14, 7, 15, 8], "texture": "#4"},
"down": {"uv": [0, 0, 0, 0], "texture": "#4"}
}
},
{
"from": [11.9, 10, 6],
"to": [14, 13, 10],
"rotation": {"angle": 0, "axis": "y", "origin": [18, 11.5, 8]},
"faces": {
"north": {"uv": [8, 3, 10, 6], "texture": "#5"},
"east": {"uv": [10, 3, 14, 6], "texture": "#5"},
"south": {"uv": [10, 3, 8, 6], "texture": "#5"},
"up": {"uv": [10, 1, 14, 3], "rotation": 90, "texture": "#5"},
"down": {"uv": [10, 1, 14, 3], "rotation": 90, "texture": "#5"}
}
},
{
"from": [2.5, 6, 7.5],
"to": [3.5, 14, 8.5],
"rotation": {"angle": 0, "axis": "y", "origin": [10, 14, 16]},
"faces": {
"north": {"uv": [15, 8, 16, 16], "texture": "#4"},
"east": {"uv": [14, 8, 15, 16], "texture": "#4"},
"south": {"uv": [15, 8, 16, 16], "texture": "#4"},
"west": {"uv": [15, 8, 16, 16], "texture": "#4"},
"up": {"uv": [14, 7, 15, 8], "texture": "#4"},
"down": {"uv": [0, 0, 0, 0], "texture": "#4"}
}
}
]
}

View file

@ -0,0 +1,119 @@
{
"credit": "Made with Blockbench",
"parent": "block/block",
"textures": {
"4": "#plate",
"5": "#bracket",
"particle": "#plate"
},
"elements": [
{
"from": [1, 0, 1],
"to": [15, 3, 15],
"rotation": {"angle": 0, "axis": "y", "origin": [1.5, 0, 1.5]},
"faces": {
"north": {"uv": [0, 10, 14, 13], "texture": "#5"},
"east": {"uv": [0, 13, 14, 16], "texture": "#5"},
"south": {"uv": [0, 10, 14, 13], "texture": "#5"},
"west": {"uv": [0, 13, 14, 16], "texture": "#5"},
"up": {"uv": [0, 2, 14, 16], "rotation": 90, "texture": "#4"},
"down": {"uv": [0, 2, 14, 16], "rotation": 270, "texture": "#4"}
}
},
{
"from": [11.9, 3, 6],
"to": [14, 6, 10],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 4.5, 8]},
"faces": {
"north": {"uv": [8, 3, 10, 6], "texture": "#5"},
"east": {"uv": [10, 3, 14, 6], "texture": "#5"},
"south": {"uv": [10, 3, 8, 6], "texture": "#5"},
"up": {"uv": [10, 1, 14, 3], "rotation": 90, "texture": "#5"},
"down": {"uv": [10, 1, 14, 3], "rotation": 90, "texture": "#5"}
}
},
{
"from": [4.1, 11, 6],
"to": [11.9, 13, 10],
"rotation": {"angle": 0, "axis": "y", "origin": [10, 4.5, 8]},
"faces": {
"north": {"uv": [8, 8, 16, 10], "rotation": 180, "texture": "#5"},
"south": {"uv": [8, 6, 16, 8], "rotation": 180, "texture": "#5"},
"up": {"uv": [8, 6, 16, 10], "texture": "#5"},
"down": {"uv": [8, 6, 16, 10], "texture": "#5"}
}
},
{
"from": [4.1, 3, 6],
"to": [11.9, 5, 10],
"rotation": {"angle": 0, "axis": "y", "origin": [10, -3.5, 8]},
"faces": {
"north": {"uv": [8, 8, 16, 10], "rotation": 180, "texture": "#5"},
"south": {"uv": [8, 6, 16, 8], "rotation": 180, "texture": "#5"},
"up": {"uv": [8, 6, 16, 10], "texture": "#5"}
}
},
{
"from": [2, 3, 6],
"to": [4.1, 6, 10],
"rotation": {"angle": 0, "axis": "y", "origin": [3, 4.5, 8]},
"faces": {
"north": {"uv": [10, 3, 8, 6], "texture": "#5"},
"south": {"uv": [8, 3, 10, 6], "texture": "#5"},
"west": {"uv": [10, 3, 14, 6], "texture": "#5"},
"up": {"uv": [10, 1, 14, 3], "rotation": 270, "texture": "#5"},
"down": {"uv": [10, 1, 14, 3], "rotation": 270, "texture": "#5"}
}
},
{
"from": [2, 10, 6],
"to": [4.1, 13, 10],
"rotation": {"angle": 0, "axis": "y", "origin": [3, 11.5, 8]},
"faces": {
"north": {"uv": [10, 3, 8, 6], "texture": "#5"},
"south": {"uv": [8, 3, 10, 6], "texture": "#5"},
"west": {"uv": [10, 3, 14, 6], "texture": "#5"},
"up": {"uv": [10, 1, 14, 3], "rotation": 270, "texture": "#5"},
"down": {"uv": [10, 1, 14, 3], "rotation": 270, "texture": "#5"}
}
},
{
"from": [12.5, 6, 7.5],
"to": [13.5, 14, 8.5],
"rotation": {"angle": 0, "axis": "y", "origin": [20, 14, 16]},
"faces": {
"north": {"uv": [15, 8, 16, 16], "texture": "#4"},
"east": {"uv": [14, 8, 15, 16], "texture": "#4"},
"south": {"uv": [15, 8, 16, 16], "texture": "#4"},
"west": {"uv": [15, 8, 16, 16], "texture": "#4"},
"up": {"uv": [14, 7, 15, 8], "texture": "#4"},
"down": {"uv": [0, 0, 0, 0], "texture": "#4"}
}
},
{
"from": [11.9, 10, 6],
"to": [14, 13, 10],
"rotation": {"angle": 0, "axis": "y", "origin": [18, 11.5, 8]},
"faces": {
"north": {"uv": [8, 3, 10, 6], "texture": "#5"},
"east": {"uv": [10, 3, 14, 6], "texture": "#5"},
"south": {"uv": [10, 3, 8, 6], "texture": "#5"},
"up": {"uv": [10, 1, 14, 3], "rotation": 90, "texture": "#5"},
"down": {"uv": [10, 1, 14, 3], "rotation": 90, "texture": "#5"}
}
},
{
"from": [2.5, 6, 7.5],
"to": [3.5, 14, 8.5],
"rotation": {"angle": 0, "axis": "y", "origin": [10, 14, 16]},
"faces": {
"north": {"uv": [15, 8, 16, 16], "texture": "#4"},
"east": {"uv": [14, 8, 15, 16], "texture": "#4"},
"south": {"uv": [15, 8, 16, 16], "texture": "#4"},
"west": {"uv": [15, 8, 16, 16], "texture": "#4"},
"up": {"uv": [14, 7, 15, 8], "texture": "#4"},
"down": {"uv": [0, 0, 0, 0], "texture": "#4"}
}
}
]
}

View file

@ -0,0 +1,110 @@
{
"credit": "Made with Blockbench",
"parent": "block/block",
"textures": {
"4": "#plate",
"5": "#bracket",
"particle": "#plate"
},
"elements": [
{
"from": [0, 1, 1],
"to": [3, 15, 15],
"faces": {
"north": {"uv": [0, 10, 14, 13], "rotation": 270, "texture": "#5"},
"east": {"uv": [0, 2, 14, 16], "rotation": 180, "texture": "#4"},
"south": {"uv": [0, 10, 14, 13], "rotation": 90, "texture": "#5"},
"west": {"uv": [0, 2, 14, 16], "texture": "#4"},
"up": {"uv": [0, 13, 14, 16], "rotation": 90, "texture": "#5"},
"down": {"uv": [0, 13, 14, 16], "rotation": 90, "texture": "#5"}
}
},
{
"from": [3, 2, 6],
"to": [6, 4.1, 10],
"faces": {
"north": {"uv": [8, 3, 10, 6], "rotation": 270, "texture": "#5"},
"east": {"uv": [10, 1, 14, 3], "rotation": 180, "texture": "#5"},
"south": {"uv": [10, 3, 8, 6], "rotation": 90, "texture": "#5"},
"west": {"uv": [10, 1, 14, 3], "rotation": 180, "texture": "#5"},
"down": {"uv": [10, 3, 14, 6], "rotation": 90, "texture": "#5"}
}
},
{
"from": [11, 4.1, 6],
"to": [13, 11.9, 10],
"faces": {
"north": {"uv": [8, 8, 16, 10], "rotation": 90, "texture": "#5"},
"east": {"uv": [8, 6, 16, 10], "rotation": 90, "texture": "#5"},
"south": {"uv": [8, 6, 16, 8], "rotation": 270, "texture": "#5"},
"west": {"uv": [8, 6, 16, 10], "rotation": 90, "texture": "#5"}
}
},
{
"from": [3, 4.1, 6],
"to": [5, 11.9, 10],
"faces": {
"north": {"uv": [8, 8, 16, 10], "rotation": 90, "texture": "#5"},
"east": {"uv": [8, 6, 16, 10], "rotation": 90, "texture": "#5"},
"south": {"uv": [8, 6, 16, 8], "rotation": 270, "texture": "#5"}
}
},
{
"from": [3, 11.9, 6],
"to": [6, 14, 10],
"faces": {
"north": {"uv": [10, 3, 8, 6], "rotation": 270, "texture": "#5"},
"east": {"uv": [10, 1, 14, 3], "texture": "#5"},
"south": {"uv": [8, 3, 10, 6], "rotation": 90, "texture": "#5"},
"west": {"uv": [10, 1, 14, 3], "texture": "#5"},
"up": {"uv": [10, 3, 14, 6], "rotation": 90, "texture": "#5"}
}
},
{
"from": [10, 11.9, 6],
"to": [13, 14, 10],
"faces": {
"north": {"uv": [10, 3, 8, 6], "rotation": 270, "texture": "#5"},
"east": {"uv": [10, 1, 14, 3], "texture": "#5"},
"south": {"uv": [8, 3, 10, 6], "rotation": 90, "texture": "#5"},
"west": {"uv": [10, 1, 14, 3], "texture": "#5"},
"up": {"uv": [10, 3, 14, 6], "rotation": 90, "texture": "#5"}
}
},
{
"from": [6, 2.5, 7.5],
"to": [14, 3.5, 8.5],
"faces": {
"north": {"uv": [15, 8, 16, 16], "rotation": 270, "texture": "#4"},
"east": {"uv": [14, 7, 15, 8], "rotation": 90, "texture": "#4"},
"south": {"uv": [15, 8, 16, 16], "rotation": 90, "texture": "#4"},
"west": {"uv": [0, 0, 0, 0], "rotation": 90, "texture": "#4"},
"up": {"uv": [15, 8, 16, 16], "rotation": 90, "texture": "#4"},
"down": {"uv": [14, 8, 15, 16], "rotation": 90, "texture": "#4"}
}
},
{
"from": [10, 2, 6],
"to": [13, 4.1, 10],
"faces": {
"north": {"uv": [8, 3, 10, 6], "rotation": 270, "texture": "#5"},
"east": {"uv": [10, 1, 14, 3], "rotation": 180, "texture": "#5"},
"south": {"uv": [10, 3, 8, 6], "rotation": 90, "texture": "#5"},
"west": {"uv": [10, 1, 14, 3], "rotation": 180, "texture": "#5"},
"down": {"uv": [10, 3, 14, 6], "rotation": 90, "texture": "#5"}
}
},
{
"from": [6, 12.5, 7.5],
"to": [14, 13.5, 8.5],
"faces": {
"north": {"uv": [15, 8, 16, 16], "rotation": 270, "texture": "#4"},
"east": {"uv": [14, 7, 15, 8], "rotation": 90, "texture": "#4"},
"south": {"uv": [15, 8, 16, 16], "rotation": 90, "texture": "#4"},
"west": {"uv": [0, 0, 0, 0], "rotation": 90, "texture": "#4"},
"up": {"uv": [15, 8, 16, 16], "rotation": 90, "texture": "#4"},
"down": {"uv": [14, 8, 15, 16], "rotation": 90, "texture": "#4"}
}
}
]
}

View file

@ -0,0 +1,110 @@
{
"credit": "Made with Blockbench",
"parent": "block/block",
"textures": {
"4": "#plate",
"5": "#bracket",
"particle": "#plate"
},
"elements": [
{
"from": [1, 0, 1],
"to": [15, 3, 15],
"rotation": {"angle": 0, "axis": "y", "origin": [1.5, 0, 1.5]},
"faces": {
"north": {"uv": [0, 10, 14, 13], "texture": "#5"},
"east": {"uv": [0, 13, 14, 16], "texture": "#5"},
"south": {"uv": [0, 10, 14, 13], "texture": "#5"},
"west": {"uv": [0, 13, 14, 16], "texture": "#5"},
"up": {"uv": [0, 2, 14, 16], "rotation": 90, "texture": "#4"},
"down": {"uv": [0, 2, 14, 16], "rotation": 270, "texture": "#4"}
}
},
{
"from": [11.9, 3, 6],
"to": [14, 6, 10],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 4.5, 8]},
"faces": {
"north": {"uv": [8, 3, 10, 6], "texture": "#5"},
"east": {"uv": [10, 3, 14, 6], "texture": "#5"},
"south": {"uv": [10, 3, 8, 6], "texture": "#5"},
"up": {"uv": [10, 1, 14, 3], "rotation": 90, "texture": "#5"},
"down": {"uv": [10, 1, 14, 3], "rotation": 90, "texture": "#5"}
}
},
{
"from": [4.1, 3, 6],
"to": [11.9, 13, 10],
"rotation": {"angle": 0, "axis": "y", "origin": [10, 4.5, 8]},
"faces": {
"north": {"uv": [0, 0, 8, 10], "rotation": 180, "texture": "#5"},
"east": {"uv": [7, 0, 8, 10], "texture": "#5"},
"south": {"uv": [0, 0, 8, 10], "rotation": 180, "texture": "#5"},
"west": {"uv": [7, 0, 8, 10], "texture": "#5"},
"up": {"uv": [8, 6, 16, 10], "texture": "#5"}
}
},
{
"from": [2, 3, 6],
"to": [4.1, 6, 10],
"rotation": {"angle": 0, "axis": "y", "origin": [3, 4.5, 8]},
"faces": {
"north": {"uv": [10, 3, 8, 6], "texture": "#5"},
"south": {"uv": [8, 3, 10, 6], "texture": "#5"},
"west": {"uv": [10, 3, 14, 6], "texture": "#5"},
"up": {"uv": [10, 1, 14, 3], "rotation": 270, "texture": "#5"},
"down": {"uv": [10, 1, 14, 3], "rotation": 270, "texture": "#5"}
}
},
{
"from": [2, 10, 6],
"to": [4.1, 13, 10],
"rotation": {"angle": 0, "axis": "y", "origin": [3, 11.5, 8]},
"faces": {
"north": {"uv": [10, 3, 8, 6], "texture": "#5"},
"south": {"uv": [8, 3, 10, 6], "texture": "#5"},
"west": {"uv": [10, 3, 14, 6], "texture": "#5"},
"up": {"uv": [10, 1, 14, 3], "rotation": 270, "texture": "#5"},
"down": {"uv": [10, 1, 14, 3], "rotation": 270, "texture": "#5"}
}
},
{
"from": [12.5, 6, 7.5],
"to": [13.5, 14, 8.5],
"rotation": {"angle": 0, "axis": "y", "origin": [20, 14, 16]},
"faces": {
"north": {"uv": [15, 8, 16, 16], "texture": "#4"},
"east": {"uv": [14, 8, 15, 16], "texture": "#4"},
"south": {"uv": [15, 8, 16, 16], "texture": "#4"},
"west": {"uv": [15, 8, 16, 16], "texture": "#4"},
"up": {"uv": [14, 7, 15, 8], "texture": "#4"},
"down": {"uv": [0, 0, 0, 0], "texture": "#4"}
}
},
{
"from": [11.9, 10, 6],
"to": [14, 13, 10],
"rotation": {"angle": 0, "axis": "y", "origin": [18, 11.5, 8]},
"faces": {
"north": {"uv": [8, 3, 10, 6], "texture": "#5"},
"east": {"uv": [10, 3, 14, 6], "texture": "#5"},
"south": {"uv": [10, 3, 8, 6], "texture": "#5"},
"up": {"uv": [10, 1, 14, 3], "rotation": 90, "texture": "#5"},
"down": {"uv": [10, 1, 14, 3], "rotation": 90, "texture": "#5"}
}
},
{
"from": [2.5, 6, 7.5],
"to": [3.5, 14, 8.5],
"rotation": {"angle": 0, "axis": "y", "origin": [10, 14, 16]},
"faces": {
"north": {"uv": [15, 8, 16, 16], "texture": "#4"},
"east": {"uv": [14, 8, 15, 16], "texture": "#4"},
"south": {"uv": [15, 8, 16, 16], "texture": "#4"},
"west": {"uv": [15, 8, 16, 16], "texture": "#4"},
"up": {"uv": [14, 7, 15, 8], "texture": "#4"},
"down": {"uv": [0, 0, 0, 0], "texture": "#4"}
}
}
]
}

View file

@ -0,0 +1,110 @@
{
"credit": "Made with Blockbench",
"parent": "block/block",
"textures": {
"4": "#plate",
"5": "#bracket",
"particle": "#plate"
},
"elements": [
{
"from": [0, 1, 1],
"to": [3, 15, 15],
"rotation": {"angle": 0, "axis": "y", "origin": [0, 14.5, 1.5]},
"faces": {
"north": {"uv": [0, 10, 14, 13], "rotation": 270, "texture": "#5"},
"east": {"uv": [0, 2, 14, 16], "rotation": 180, "texture": "#4"},
"south": {"uv": [0, 10, 14, 13], "rotation": 90, "texture": "#5"},
"west": {"uv": [0, 2, 14, 16], "texture": "#4"},
"up": {"uv": [0, 13, 14, 16], "rotation": 90, "texture": "#5"},
"down": {"uv": [0, 13, 14, 16], "rotation": 90, "texture": "#5"}
}
},
{
"from": [3, 2, 6],
"to": [6, 4.1, 10],
"rotation": {"angle": 0, "axis": "y", "origin": [4.5, 8, 8]},
"faces": {
"north": {"uv": [8, 3, 10, 6], "rotation": 270, "texture": "#5"},
"east": {"uv": [10, 1, 14, 3], "rotation": 180, "texture": "#5"},
"south": {"uv": [10, 3, 8, 6], "rotation": 90, "texture": "#5"},
"west": {"uv": [10, 1, 14, 3], "rotation": 180, "texture": "#5"},
"down": {"uv": [10, 3, 14, 6], "rotation": 90, "texture": "#5"}
}
},
{
"from": [3, 4.1, 6],
"to": [13, 11.9, 10],
"rotation": {"angle": 0, "axis": "y", "origin": [4.5, 6, 8]},
"faces": {
"north": {"uv": [0, 0, 8, 10], "rotation": 90, "texture": "#5"},
"east": {"uv": [8, 6, 16, 10], "rotation": 90, "texture": "#5"},
"south": {"uv": [0, 0, 8, 10], "rotation": 270, "texture": "#5"},
"up": {"uv": [7, 0, 8, 10], "rotation": 90, "texture": "#5"},
"down": {"uv": [7, 0, 8, 10], "rotation": 90, "texture": "#5"}
}
},
{
"from": [3, 11.9, 6],
"to": [6, 14, 10],
"rotation": {"angle": 0, "axis": "y", "origin": [4.5, 13, 8]},
"faces": {
"north": {"uv": [10, 3, 8, 6], "rotation": 270, "texture": "#5"},
"east": {"uv": [10, 1, 14, 3], "texture": "#5"},
"south": {"uv": [8, 3, 10, 6], "rotation": 90, "texture": "#5"},
"west": {"uv": [10, 1, 14, 3], "texture": "#5"},
"up": {"uv": [10, 3, 14, 6], "rotation": 90, "texture": "#5"}
}
},
{
"from": [10, 11.9, 6],
"to": [13, 14, 10],
"rotation": {"angle": 0, "axis": "y", "origin": [11.5, 13, 8]},
"faces": {
"north": {"uv": [10, 3, 8, 6], "rotation": 270, "texture": "#5"},
"east": {"uv": [10, 1, 14, 3], "texture": "#5"},
"south": {"uv": [8, 3, 10, 6], "rotation": 90, "texture": "#5"},
"west": {"uv": [10, 1, 14, 3], "texture": "#5"},
"up": {"uv": [10, 3, 14, 6], "rotation": 90, "texture": "#5"}
}
},
{
"from": [6, 2.5, 7.5],
"to": [14, 3.5, 8.5],
"rotation": {"angle": 0, "axis": "y", "origin": [14, -4, 16]},
"faces": {
"north": {"uv": [15, 8, 16, 16], "rotation": 270, "texture": "#4"},
"east": {"uv": [14, 7, 15, 8], "rotation": 90, "texture": "#4"},
"south": {"uv": [15, 8, 16, 16], "rotation": 90, "texture": "#4"},
"west": {"uv": [0, 0, 0, 0], "rotation": 90, "texture": "#4"},
"up": {"uv": [15, 8, 16, 16], "rotation": 90, "texture": "#4"},
"down": {"uv": [14, 8, 15, 16], "rotation": 90, "texture": "#4"}
}
},
{
"from": [10, 2, 6],
"to": [13, 4.1, 10],
"rotation": {"angle": 0, "axis": "y", "origin": [11.5, -2, 8]},
"faces": {
"north": {"uv": [8, 3, 10, 6], "rotation": 270, "texture": "#5"},
"east": {"uv": [10, 1, 14, 3], "rotation": 180, "texture": "#5"},
"south": {"uv": [10, 3, 8, 6], "rotation": 90, "texture": "#5"},
"west": {"uv": [10, 1, 14, 3], "rotation": 180, "texture": "#5"},
"down": {"uv": [10, 3, 14, 6], "rotation": 90, "texture": "#5"}
}
},
{
"from": [6, 12.5, 7.5],
"to": [14, 13.5, 8.5],
"rotation": {"angle": 0, "axis": "y", "origin": [14, 6, 16]},
"faces": {
"north": {"uv": [15, 8, 16, 16], "rotation": 270, "texture": "#4"},
"east": {"uv": [14, 7, 15, 8], "rotation": 90, "texture": "#4"},
"south": {"uv": [15, 8, 16, 16], "rotation": 90, "texture": "#4"},
"west": {"uv": [0, 0, 0, 0], "rotation": 90, "texture": "#4"},
"up": {"uv": [15, 8, 16, 16], "rotation": 90, "texture": "#4"},
"down": {"uv": [14, 8, 15, 16], "rotation": 90, "texture": "#4"}
}
}
]
}

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