Fluid Delivery

- Fluid Tanks and Creative Fluid Tanks now form a combined fluid inventory on contraptions
- Added the Portable Fluid Interface
- Fixed tanks placed with nbt not clamping their contained fluids
- Item Storage information on Contraptions no longer get sent to the client
- Combined fluid storage synchronizes to the client and applies new contents to the corresponding mounted TE renderers
- Fixed motion of dripping potion particles from fluid pipe flow indication
- Portable Storage interfaces now interrupt their connection when receiving redstone power
This commit is contained in:
simibubi 2020-11-25 18:54:59 +01:00
parent 0d9a6cc8c3
commit 8ff98dc3fb
59 changed files with 901 additions and 206 deletions

View file

@ -137,7 +137,7 @@ de8a40b7daf1497d5aecee47a43b3e0b1d030b00 assets/create/blockstates/fancy_scoria_
fc9ac0a7e7191b93516719455a17177fa6524ecc assets/create/blockstates/fancy_weathered_limestone_bricks_slab.json
b2a7c321b1795f20e7433f81a55ce4683de081b8 assets/create/blockstates/fancy_weathered_limestone_bricks_stairs.json
6372fe02ba0065acb0758121c45a15a1a8fdc5de assets/create/blockstates/fancy_weathered_limestone_bricks_wall.json
3d97226b5e8d8f70ed08e45e78db1faf78d5e28b assets/create/blockstates/fluid_pipe.json
fe9169716dd21a81a3710a89f0a9b7ea4dcd4d51 assets/create/blockstates/fluid_pipe.json
f0eaab18e16c4f3f65ebf3b55b08f0dc445720fe assets/create/blockstates/fluid_tank.json
5408d92ab02af86539ac42971d4033545970bb3a assets/create/blockstates/fluid_valve.json
e9da1794b6ece7f9aa8bcb43d42c23a55446133b assets/create/blockstates/flywheel.json
@ -322,6 +322,7 @@ c8467d55bc22d2e2256b8b732c06c9fdc64d336f assets/create/blockstates/polished_weat
5d811eab3c5e8411f98e2ea98d93d35955ce18fc assets/create/blockstates/polished_weathered_limestone_slab.json
acec6cdebe772ca72de94a85d98199e827495acb assets/create/blockstates/polished_weathered_limestone_stairs.json
f42ad32aefcfa7ccc6287f57ee1a5f092b65126f assets/create/blockstates/polished_weathered_limestone_wall.json
3bb571d0a2597907bf3a30686b4bfa0841ac990a assets/create/blockstates/portable_fluid_interface.json
1b70b4e5792dccd2110b84e209016ac258005e28 assets/create/blockstates/portable_storage_interface.json
8296d43d5f1c2113012d127038fb319af83aaee4 assets/create/blockstates/powered_latch.json
e8b0a401c10d1ba67ed71ba31bd5f9bc28571b65 assets/create/blockstates/powered_toggle_latch.json
@ -392,17 +393,17 @@ a3a11524cd3515fc01d905767b4b7ea782adaf03 assets/create/blockstates/yellow_seat.j
6801fa1f466f172700e573e5b8ee8ee5f9ca4583 assets/create/blockstates/yellow_valve_handle.json
7f39521b211441f5c3e06d60c5978cebe16cacfb assets/create/blockstates/zinc_block.json
b7181bcd8182b2f17088e5aa881f374c9c65470c assets/create/blockstates/zinc_ore.json
04f295b9cbe610bb3664e956437ae68d2a0776ad assets/create/lang/en_ud.json
3912eddc0fdb76afe08961c9d9ad9fe776fbbef5 assets/create/lang/en_us.json
66e50a9482f186f3b0b066bcc7a8d6194b5892b4 assets/create/lang/unfinished/de_de.json
d0adae002c2ca46ad24d4f08037308334c239c69 assets/create/lang/unfinished/fr_fr.json
98b6589d85a68eb4460a7d2da96816b026436c14 assets/create/lang/unfinished/it_it.json
9a9477f8257367993760fbc9e4b65a2d8190b868 assets/create/lang/unfinished/ja_jp.json
e9e466d962ccba589d6d14e37c82e98076a3e614 assets/create/lang/unfinished/ko_kr.json
9e8277f247b069bb45fd45b086a5138ec160847f assets/create/lang/unfinished/nl_nl.json
707ec25a7f45dd3dca8b96d4031b38d1be64f840 assets/create/lang/unfinished/pt_br.json
f645e781db3e254d64ea4b20a553e713bfca3610 assets/create/lang/unfinished/ru_ru.json
1e8a48a6ba2d7ec7947c312835c332e869757526 assets/create/lang/unfinished/zh_cn.json
67f9a92292948241e01ce6043445b2b3ddcf5350 assets/create/lang/en_ud.json
ea9f7788b7cae3ddd4ba1ae74c54f558d6b3f584 assets/create/lang/en_us.json
d2741d202f1b76c0c57fbd25d5f35cfab258edb0 assets/create/lang/unfinished/de_de.json
ce08c4a4163e667a5c20dfd241cb56b0ff5d064e assets/create/lang/unfinished/fr_fr.json
6fe663867f28389fdac5ac75a12089ca7279a0cb assets/create/lang/unfinished/it_it.json
28b1bbb303a20f43266ae089b5d8b920523ee854 assets/create/lang/unfinished/ja_jp.json
cfc50d41b77b5dfeb49da61b95496a65b3d71169 assets/create/lang/unfinished/ko_kr.json
9f9e817483a92c960db5a6cdd30e0c9e0ac0b2f3 assets/create/lang/unfinished/nl_nl.json
6d638fa512c863203ff7207c9a68782ba4fd9997 assets/create/lang/unfinished/pt_br.json
0dc96a32325dc79e7f0cf980a7011475aa22ecc3 assets/create/lang/unfinished/ru_ru.json
311937a993d6c186ba4c433cd7befca8e4da6d89 assets/create/lang/unfinished/zh_cn.json
846200eb548d3bfa2e77b41039de159b4b6cfb45 assets/create/models/block/acacia_window.json
1930fa3a3c98d53dd19e4ee7f55bc27fd47aa281 assets/create/models/block/acacia_window_pane_noside.json
1763ea2c9b981d187f5031ba608f3d5d3be3986a assets/create/models/block/acacia_window_pane_noside_alt.json
@ -1438,6 +1439,7 @@ e95125318055b8557afd7d108488cf0bdd81fe49 assets/create/models/item/polished_scor
68fb04f7a89c8117bb641e347df9bfc1f1248335 assets/create/models/item/polished_weathered_limestone_slab.json
6d92ee7112aa20e8a1adfe73d8933031c299bed1 assets/create/models/item/polished_weathered_limestone_stairs.json
b4995fb4799f33508cd6bf2ded80c0b3e866ad43 assets/create/models/item/polished_weathered_limestone_wall.json
0e5638cdbf04d7af2222ec15fbe1d960385ea237 assets/create/models/item/portable_fluid_interface.json
3bc60b0d9884c2ee0f1dd530e90fceb699eea737 assets/create/models/item/portable_storage_interface.json
d3cfc1a1137c4bc98848947d425d2972df144c95 assets/create/models/item/powdered_obsidian.json
1e501c1f2e9250aaaadcf17db62646d08177d4e1 assets/create/models/item/powered_latch.json
@ -1652,6 +1654,7 @@ ccd49c33260333ba850d0b843c4913cb6371eee9 data/create/advancements/recipes/create
ca21e2192a2fea0f112764f96c928d337762158b data/create/advancements/recipes/create.base/crafting/kinetics/pink_seat_from_other_seat.json
6c11444884679c4dd03d43f5893fca5cdc271915 data/create/advancements/recipes/create.base/crafting/kinetics/pink_valve_handle_from_other_valve_handle.json
960d03f13b383fca0d9b7d3a2885da346d97c4ef data/create/advancements/recipes/create.base/crafting/kinetics/piston_extension_pole.json
164563947ebd951d36a839ee0787714b104ba090 data/create/advancements/recipes/create.base/crafting/kinetics/portable_fluid_interface.json
3190b3800152879614127c7cd2616e5607f1a0b1 data/create/advancements/recipes/create.base/crafting/kinetics/portable_storage_interface.json
02258b70f1db3d91f0ccb5a5ffd362349f8f359d data/create/advancements/recipes/create.base/crafting/kinetics/propeller.json
d2a430820a87c24104729eede57628c6a92b277e data/create/advancements/recipes/create.base/crafting/kinetics/purple_seat.json
@ -2465,6 +2468,7 @@ c7029af40b6f5dd2cd8f2ae7dfb89b37074624e6 data/create/loot_tables/blocks/polished
93f7be402a8088d33a94954572e111bcd71f11c8 data/create/loot_tables/blocks/polished_weathered_limestone_slab.json
6ef650c723d409c7a678ffac45212e22e37581c0 data/create/loot_tables/blocks/polished_weathered_limestone_stairs.json
58715bc033e4740dbb754f91c93a22b9d06828e6 data/create/loot_tables/blocks/polished_weathered_limestone_wall.json
ac945ab9e78d52daff38b9c288824ec6f643b23a data/create/loot_tables/blocks/portable_fluid_interface.json
fbe98efcb1a5970b6795fdbbb671fee704c0945f data/create/loot_tables/blocks/portable_storage_interface.json
6a46f00d9de7050eb9748d5dbed182caa6b29949 data/create/loot_tables/blocks/powered_latch.json
a3fb7d3e3bf9dc73ce754002f10c469d57db1f71 data/create/loot_tables/blocks/powered_toggle_latch.json
@ -2664,7 +2668,8 @@ af871a02d363a619fff8e9dde753aa417b265a80 data/create/recipes/crafting/kinetics/p
840dc5aac716e3d1b79883e8db4bf56f2dc427f9 data/create/recipes/crafting/kinetics/pink_seat_from_other_seat.json
7e73bcde2b599f1ae5a241dd707c8ab6ce8c5a6e data/create/recipes/crafting/kinetics/pink_valve_handle_from_other_valve_handle.json
5399c3496a90bed9428c48fdd334ad4f763cbf9a data/create/recipes/crafting/kinetics/piston_extension_pole.json
0b09786f6d9823c6eddc91c3a6837377690dde49 data/create/recipes/crafting/kinetics/portable_storage_interface.json
a8e996bed77d3d20725f9d592c250392b3adb106 data/create/recipes/crafting/kinetics/portable_fluid_interface.json
7ed5699349faf2981228769c873057105a5ea3ea data/create/recipes/crafting/kinetics/portable_storage_interface.json
16199a6729005a279854cb1838401f6e73bdebae data/create/recipes/crafting/kinetics/propeller.json
76ba751b65d312d1b34229d76fff2111b593091a data/create/recipes/crafting/kinetics/purple_seat.json
e6c462d64e1de9c7fca95f9c9a25b8d1575979da data/create/recipes/crafting/kinetics/purple_seat_from_other_seat.json

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -631,6 +631,15 @@ public class AllBlocks {
.transform(customItemModel())
.register();
public static final BlockEntry<PortableStorageInterfaceBlock> PORTABLE_FLUID_INTERFACE =
REGISTRATE.block("portable_fluid_interface", PortableStorageInterfaceBlock::forFluids)
.initialProperties(SharedProperties::softMetal)
.blockstate((c, p) -> p.directionalBlock(c.get(), AssetLookup.partialBaseModel(c, p)))
.onRegister(addMovementBehaviour(new PortableStorageInterfaceMovement()))
.item()
.transform(customItemModel())
.register();
// Contraptions
public static final BlockEntry<MechanicalPistonBlock> MECHANICAL_PISTON =
@ -791,7 +800,7 @@ public class AllBlocks {
.register();
public static final BlockEntry<PortableStorageInterfaceBlock> PORTABLE_STORAGE_INTERFACE =
REGISTRATE.block("portable_storage_interface", PortableStorageInterfaceBlock::new)
REGISTRATE.block("portable_storage_interface", PortableStorageInterfaceBlock::forItems)
.initialProperties(SharedProperties::stone)
.blockstate((c, p) -> p.directionalBlock(c.get(), AssetLookup.partialBaseModel(c, p)))
.onRegister(addMovementBehaviour(new PortableStorageInterfaceMovement()))

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -4,45 +4,42 @@ import java.util.List;
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.item.ItemHandlerWrapper;
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
import com.simibubi.create.foundation.utility.LerpedFloat;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.Direction;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.MathHelper;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.IItemHandlerModifiable;
public class PortableStorageInterfaceTileEntity extends SmartTileEntity {
public abstract class PortableStorageInterfaceTileEntity extends SmartTileEntity {
protected int transferTimer;
protected float distance;
protected LazyOptional<IItemHandlerModifiable> capability;
protected LerpedFloat connectionAnimation;
protected boolean powered;
public PortableStorageInterfaceTileEntity(TileEntityType<?> tileEntityTypeIn) {
super(tileEntityTypeIn);
transferTimer = 0;
capability = LazyOptional.empty();
connectionAnimation = LerpedFloat.linear().startWithValue(0);
connectionAnimation = LerpedFloat.linear()
.startWithValue(0);
powered = false;
}
public void startTransferringTo(Contraption contraption, float distance) {
capability.invalidate();
capability = LazyOptional.of(() -> new InterfaceItemHandler(contraption.inventory));
this.distance = distance;
startConnecting();
notifyUpdate();
}
protected abstract void stopTransferring();
protected abstract void invalidateCapability();
@Override
public void tick() {
super.tick();
@ -50,8 +47,8 @@ public class PortableStorageInterfaceTileEntity extends SmartTileEntity {
if (transferTimer > 0) {
transferTimer--;
if (transferTimer == 0)
capability.invalidate();
if (transferTimer == 0 || powered)
stopTransferring();
}
boolean isConnected = isConnected();
@ -69,11 +66,18 @@ public class PortableStorageInterfaceTileEntity extends SmartTileEntity {
connectionAnimation.setValue(progress);
}
@Override
public void remove() {
super.remove();
invalidateCapability();
}
@Override
protected void read(CompoundNBT compound, boolean clientPacket) {
super.read(compound, clientPacket);
transferTimer = compound.getInt("Timer");
distance = compound.getFloat("Distance");
powered = compound.getBoolean("Powered");
}
@Override
@ -81,6 +85,19 @@ public class PortableStorageInterfaceTileEntity extends SmartTileEntity {
super.write(compound, clientPacket);
compound.putInt("Timer", transferTimer);
compound.putFloat("Distance", distance);
compound.putBoolean("Powered", powered);
}
public void neighbourChanged() {
boolean isBlockPowered = world.isBlockPowered(pos);
if (isBlockPowered == powered)
return;
powered = isBlockPowered;
sendData();
}
public boolean isPowered() {
return powered;
}
@Override
@ -106,13 +123,6 @@ public class PortableStorageInterfaceTileEntity extends SmartTileEntity {
return distance;
}
@Override
public <T> LazyOptional<T> getCapability(Capability<T> cap, Direction side) {
if (isItemHandlerCap(cap))
return capability.cast();
return super.getCapability(cap, side);
}
public void startConnecting() {
transferTimer = getTransferTimeout() * 2;
}
@ -130,32 +140,4 @@ public class PortableStorageInterfaceTileEntity extends SmartTileEntity {
@Override
public void addBehaviours(List<TileEntityBehaviour> behaviours) {}
class InterfaceItemHandler extends ItemHandlerWrapper {
public InterfaceItemHandler(IItemHandlerModifiable wrapped) {
super(wrapped);
}
@Override
public ItemStack extractItem(int slot, int amount, boolean simulate) {
if (!isConnected())
return ItemStack.EMPTY;
ItemStack extractItem = super.extractItem(slot, amount, simulate);
if (!simulate && !extractItem.isEmpty())
onContentTransferred();
return extractItem;
}
@Override
public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) {
if (!isConnected())
return stack;
ItemStack insertItem = super.insertItem(slot, stack, simulate);
if (!simulate && !insertItem.equals(stack, false))
onContentTransferred();
return insertItem;
}
}
}

View file

@ -223,6 +223,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit
if (!initialized)
contraptionInitialize();
contraption.onEntityTick(world);
tickContraption();
super.tick();
}
@ -351,22 +352,6 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit
this.dataManager.register(STALLED, false);
}
@Override
protected void readAdditional(CompoundNBT compound) {
initialized = compound.getBoolean("Initialized");
contraption = Contraption.fromNBT(world, compound.getCompound("Contraption"));
contraption.entity = this;
dataManager.set(STALLED, compound.getBoolean("Stalled"));
}
@Override
protected void writeAdditional(CompoundNBT compound) {
if (contraption != null)
compound.put("Contraption", contraption.writeNBT());
compound.putBoolean("Stalled", isStalled());
compound.putBoolean("Initialized", initialized);
}
@Override
public IPacket<?> createSpawnPacket() {
return NetworkHooks.getEntitySpawningPacket(this);
@ -375,13 +360,37 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit
@Override
public void writeSpawnData(PacketBuffer buffer) {
CompoundNBT compound = new CompoundNBT();
writeAdditional(compound);
writeAdditional(compound, true);
buffer.writeCompoundTag(compound);
}
@Override
protected final void writeAdditional(CompoundNBT compound) {
writeAdditional(compound, false);
}
protected void writeAdditional(CompoundNBT compound, boolean spawnPacket) {
if (contraption != null)
compound.put("Contraption", contraption.writeNBT(spawnPacket));
compound.putBoolean("Stalled", isStalled());
compound.putBoolean("Initialized", initialized);
}
@Override
public void readSpawnData(PacketBuffer additionalData) {
readAdditional(additionalData.readCompoundTag());
readAdditional(additionalData.readCompoundTag(), true);
}
@Override
protected final void readAdditional(CompoundNBT compound) {
readAdditional(compound, false);
}
protected void readAdditional(CompoundNBT compound, boolean spawnData) {
initialized = compound.getBoolean("Initialized");
contraption = Contraption.fromNBT(world, compound.getCompound("Contraption"), spawnData);
contraption.entity = this;
dataManager.set(STALLED, compound.getBoolean("Stalled"));
}
public void disassemble() {

View file

@ -44,6 +44,7 @@ import com.simibubi.create.content.contraptions.relays.belt.BeltBlock;
import com.simibubi.create.content.logistics.block.inventories.AdjustableCrateBlock;
import com.simibubi.create.content.logistics.block.redstone.RedstoneContactBlock;
import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.fluid.CombinedTankWrapper;
import com.simibubi.create.foundation.utility.BlockFace;
import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.NBTHelper;
@ -81,6 +82,10 @@ import net.minecraft.world.World;
import net.minecraft.world.gen.feature.template.Template.BlockInfo;
import net.minecraftforge.common.util.Constants.BlockFlags;
import net.minecraftforge.common.util.Constants.NBT;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.IFluidTank;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.fluids.capability.templates.FluidTank;
import net.minecraftforge.items.IItemHandlerModifiable;
import net.minecraftforge.items.wrapper.CombinedInvWrapper;
@ -88,12 +93,14 @@ public abstract class Contraption {
public AbstractContraptionEntity entity;
public CombinedInvWrapper inventory;
public CombinedTankWrapper fluidInventory;
public AxisAlignedBB bounds;
public BlockPos anchor;
public boolean stalled;
protected Map<BlockPos, BlockInfo> blocks;
protected Map<BlockPos, MountedStorage> storage;
protected Map<BlockPos, MountedFluidStorage> fluidStorage;
protected List<MutablePair<BlockInfo, MovementContext>> actors;
protected Set<Pair<BlockPos, Direction>> superglue;
protected List<BlockPos> seats;
@ -105,7 +112,7 @@ public abstract class Contraption {
private List<BlockFace> pendingSubContraptions;
// Client
public List<TileEntity> renderedTileEntities;
public Map<BlockPos, TileEntity> renderedTileEntities;
public Contraption() {
blocks = new HashMap<>();
@ -114,9 +121,10 @@ public abstract class Contraption {
actors = new ArrayList<>();
superglue = new HashSet<>();
seatMapping = new HashMap<>();
fluidStorage = new HashMap<>();
glueToRemove = new ArrayList<>();
initialPassengers = new HashMap<>();
renderedTileEntities = new ArrayList<>();
renderedTileEntities = new HashMap<>();
pendingSubContraptions = new ArrayList<>();
stabilizedSubContraptions = new HashMap<>();
}
@ -140,10 +148,10 @@ public abstract class Contraption {
return true;
}
public static Contraption fromNBT(World world, CompoundNBT nbt) {
public static Contraption fromNBT(World world, CompoundNBT nbt, boolean spawnData) {
String type = nbt.getString("Type");
Contraption contraption = AllContraptionTypes.fromType(type);
contraption.readNBT(world, nbt);
contraption.readNBT(world, nbt, spawnData);
return contraption;
}
@ -195,6 +203,13 @@ public abstract class Contraption {
.map(MountedStorage::getItemHandler)
.collect(Collectors.toList());
inventory = new CombinedInvWrapper(Arrays.copyOf(list.toArray(), list.size(), IItemHandlerModifiable[].class));
List<IFluidHandler> fluidHandlers = fluidStorage.values()
.stream()
.map(MountedFluidStorage::getFluidHandler)
.collect(Collectors.toList());
fluidInventory = new CombinedTankWrapper(
Arrays.copyOf(fluidHandlers.toArray(), fluidHandlers.size(), IFluidHandler[].class));
}
public void onEntityInitialize(World world, AbstractContraptionEntity contraptionEntity) {
@ -218,6 +233,10 @@ public abstract class Contraption {
}
}
public void onEntityTick(World world) {
fluidStorage.forEach((pos, mfs) -> mfs.tick(entity, pos, world.isRemote));
}
protected boolean moveBlock(World world, BlockPos pos, Direction forcedDirection, List<BlockPos> frontier,
Set<BlockPos> visited) {
visited.add(pos);
@ -449,6 +468,8 @@ public abstract class Contraption {
TileEntity te = pair.getValue();
if (te != null && MountedStorage.canUseAsStorage(te))
storage.put(localPos, new MountedStorage(te));
if (te != null && MountedFluidStorage.canUseAsStorage(te))
fluidStorage.put(localPos, new MountedFluidStorage(te));
if (AllMovementBehaviours.contains(captured.state.getBlock()))
actors.add(MutablePair.of(blockInfo, null));
}
@ -489,7 +510,7 @@ public abstract class Contraption {
return pos.equals(anchor);
}
public void readNBT(World world, CompoundNBT nbt) {
public void readNBT(World world, CompoundNBT nbt, boolean spawnData) {
blocks.clear();
renderedTileEntities.clear();
@ -528,7 +549,7 @@ public abstract class Contraption {
if (te instanceof KineticTileEntity)
((KineticTileEntity) te).setSpeed(0);
te.getBlockState();
renderedTileEntities.add(te);
renderedTileEntities.put(info.pos, te);
}
});
@ -560,6 +581,24 @@ public abstract class Contraption {
NBTHelper.iterateCompoundList(nbt.getList("Storage", NBT.TAG_COMPOUND), c -> storage
.put(NBTUtil.readBlockPos(c.getCompound("Pos")), MountedStorage.deserialize(c.getCompound("Data"))));
fluidStorage.clear();
NBTHelper.iterateCompoundList(nbt.getList("FluidStorage", NBT.TAG_COMPOUND), c -> fluidStorage
.put(NBTUtil.readBlockPos(c.getCompound("Pos")), MountedFluidStorage.deserialize(c.getCompound("Data"))));
if (spawnData)
fluidStorage.forEach((pos, mfs) -> {
TileEntity tileEntity = renderedTileEntities.get(pos);
if (!(tileEntity instanceof FluidTankTileEntity))
return;
FluidTankTileEntity tank = (FluidTankTileEntity) tileEntity;
IFluidTank tankInventory = tank.getTankInventory();
if (tankInventory instanceof FluidTank)
((FluidTank) tankInventory).setFluid(mfs.tank.getFluid());
tank.getFluidLevel()
.start(tank.getFillState());
mfs.assignTileEntity(tank);
});
IItemHandlerModifiable[] handlers = new IItemHandlerModifiable[storage.size()];
int index = 0;
for (MountedStorage mountedStorage : storage.values())
@ -573,7 +612,7 @@ public abstract class Contraption {
anchor = NBTUtil.readBlockPos(nbt.getCompound("Anchor"));
}
public CompoundNBT writeNBT() {
public CompoundNBT writeNBT(boolean spawnPacket) {
CompoundNBT nbt = new CompoundNBT();
nbt.putString("Type", getType().id);
ListNBT blocksNBT = new ListNBT();
@ -606,14 +645,27 @@ public abstract class Contraption {
}
ListNBT storageNBT = new ListNBT();
for (BlockPos pos : storage.keySet()) {
if (!spawnPacket) {
for (BlockPos pos : storage.keySet()) {
CompoundNBT c = new CompoundNBT();
MountedStorage mountedStorage = storage.get(pos);
if (!mountedStorage.isValid())
continue;
c.put("Pos", NBTUtil.writeBlockPos(pos));
c.put("Data", mountedStorage.serialize());
storageNBT.add(c);
}
}
ListNBT fluidStorageNBT = new ListNBT();
for (BlockPos pos : fluidStorage.keySet()) {
CompoundNBT c = new CompoundNBT();
MountedStorage mountedStorage = storage.get(pos);
MountedFluidStorage mountedStorage = fluidStorage.get(pos);
if (!mountedStorage.isValid())
continue;
c.put("Pos", NBTUtil.writeBlockPos(pos));
c.put("Data", mountedStorage.serialize());
storageNBT.add(c);
fluidStorageNBT.add(c);
}
nbt.put("Seats", NBTHelper.writeCompoundList(getSeats(), NBTUtil::writeBlockPos));
@ -636,6 +688,7 @@ public abstract class Contraption {
nbt.put("Actors", actorsNBT);
nbt.put("Superglue", superglueNBT);
nbt.put("Storage", storageNBT);
nbt.put("FluidStorage", fluidStorageNBT);
nbt.put("Anchor", NBTUtil.writeBlockPos(anchor));
nbt.putBoolean("Stalled", stalled);
@ -650,6 +703,8 @@ public abstract class Contraption {
public void removeBlocksFromWorld(IWorld world, BlockPos offset) {
storage.values()
.forEach(MountedStorage::removeStorageFromWorld);
fluidStorage.values()
.forEach(MountedFluidStorage::removeStorageFromWorld);
glueToRemove.forEach(SuperGlueEntity::remove);
for (boolean brittles : Iterate.trueAndFalse) {
@ -750,6 +805,12 @@ public abstract class Contraption {
if (mountedStorage.isValid())
mountedStorage.addStorageToWorld(tileEntity);
}
if (fluidStorage.containsKey(block.pos)) {
MountedFluidStorage mountedStorage = fluidStorage.get(block.pos);
if (mountedStorage.isValid())
mountedStorage.addStorageToWorld(tileEntity);
}
}
}
}
@ -868,4 +929,10 @@ public abstract class Contraption {
return actors;
}
public void updateContainedFluid(BlockPos localPos, FluidStack containedFluid) {
MountedFluidStorage mountedFluidStorage = fluidStorage.get(localPos);
if (mountedFluidStorage != null)
mountedFluidStorage.updateFluid(containedFluid);
}
}

View file

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

View file

@ -67,8 +67,8 @@ public class ControlledContraptionEntity extends AbstractContraptionEntity {
}
@Override
protected void readAdditional(CompoundNBT compound) {
super.readAdditional(compound);
protected void readAdditional(CompoundNBT compound, boolean spawnPacket) {
super.readAdditional(compound, spawnPacket);
controllerPos = NBTUtil.readBlockPos(compound.getCompound("Controller"));
if (compound.contains("Axis"))
rotationAxis = NBTHelper.readEnum(compound, "Axis", Axis.class);
@ -76,8 +76,8 @@ public class ControlledContraptionEntity extends AbstractContraptionEntity {
}
@Override
protected void writeAdditional(CompoundNBT compound) {
super.writeAdditional(compound);
protected void writeAdditional(CompoundNBT compound, boolean spawnPacket) {
super.writeAdditional(compound, spawnPacket);
compound.put("Controller", NBTUtil.writeBlockPos(controllerPos));
if (rotationAxis != null)
NBTHelper.writeEnum(compound, "Axis", rotationAxis);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -167,7 +167,7 @@ public class MinecartContraptionItem extends Item {
intialOrientation =
Optional.of(NBTHelper.readEnum(contraptionTag, "InitialOrientation", Direction.class));
Contraption mountedContraption = Contraption.fromNBT(world, contraptionTag);
Contraption mountedContraption = Contraption.fromNBT(world, contraptionTag, false);
OrientedContraptionEntity contraptionEntity =
OrientedContraptionEntity.create(world, mountedContraption, intialOrientation);
@ -239,7 +239,7 @@ public class MinecartContraptionItem extends Item {
return stack;
CompoundNBT tag = entity.getContraption()
.writeNBT();
.writeNBT(false);
tag.remove("UUID");
tag.remove("Pos");
tag.remove("Motion");

View file

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

View file

@ -203,20 +203,20 @@ public class PistonContraption extends TranslatingContraption {
}
@Override
public void readNBT(World world, CompoundNBT nbt) {
super.readNBT(world, nbt);
public void readNBT(World world, CompoundNBT nbt, boolean spawnData) {
super.readNBT(world, nbt, spawnData);
initialExtensionProgress = nbt.getInt("InitialLength");
extensionLength = nbt.getInt("ExtensionLength");
orientation = Direction.byIndex(nbt.getInt("Orientation"));
}
@Override
public CompoundNBT writeNBT() {
CompoundNBT nbt = super.writeNBT();
nbt.putInt("InitialLength", initialExtensionProgress);
nbt.putInt("ExtensionLength", extensionLength);
nbt.putInt("Orientation", orientation.getIndex());
return nbt;
public CompoundNBT writeNBT(boolean spawnPacket) {
CompoundNBT tag = super.writeNBT(spawnPacket);
tag.putInt("InitialLength", initialExtensionProgress);
tag.putInt("ExtensionLength", extensionLength);
tag.putInt("Orientation", orientation.getIndex());
return tag;
}
}

View file

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

View file

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

View file

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

View file

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

View file

@ -12,6 +12,7 @@ import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.fluids.FluidStack;
public class FluidTankItem extends BlockItem {
@ -41,6 +42,13 @@ public class FluidTankItem extends BlockItem {
nbt.remove("Height");
nbt.remove("Controller");
nbt.remove("LastKnownPos");
if (nbt.contains("TankContent")) {
FluidStack fluid = FluidStack.loadFluidStackFromNBT(nbt.getCompound("TankContent"));
if (!fluid.isEmpty()) {
fluid.setAmount(Math.min(FluidTankTileEntity.getCapacityMultiplier(), fluid.getAmount()));
nbt.put("TankContent", fluid.writeToNBT(new CompoundNBT()));
}
}
}
return super.onBlockPlaced(p_195943_1_, p_195943_2_, p_195943_3_, p_195943_4_, p_195943_5_);
}

View file

@ -354,7 +354,7 @@ public class FluidTankTileEntity extends SmartTileEntity {
fluidLevel.withSpeed(compound.contains("LazySync") ? 1 / 8f : 1 / 2f);
}
protected float getFillState() {
public float getFillState() {
return (float) tankInventory.getFluidAmount() / tankInventory.getCapacity();
}
@ -414,7 +414,7 @@ public class FluidTankTileEntity extends SmartTileEntity {
return MAX_SIZE;
}
protected static int getCapacityMultiplier() {
public static int getCapacityMultiplier() {
return AllConfigs.SERVER.fluids.fluidTankCapacity.get() * 1000;
}
@ -422,4 +422,12 @@ public class FluidTankTileEntity extends SmartTileEntity {
return AllConfigs.SERVER.fluids.fluidTankMaxHeight.get();
}
public InterpolatedChasingValue getFluidLevel() {
return fluidLevel;
}
public void setFluidLevel(InterpolatedChasingValue fluidLevel) {
this.fluidLevel = fluidLevel;
}
}

View file

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

View file

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

View file

@ -9,6 +9,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.Con
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionStallPacket;
import com.simibubi.create.content.contraptions.components.structureMovement.glue.GlueEffectPacket;
import com.simibubi.create.content.contraptions.components.structureMovement.sync.ClientMotionPacket;
import com.simibubi.create.content.contraptions.components.structureMovement.sync.ContraptionFluidPacket;
import com.simibubi.create.content.contraptions.components.structureMovement.sync.ContraptionInteractionPacket;
import com.simibubi.create.content.contraptions.components.structureMovement.sync.ContraptionSeatMappingPacket;
import com.simibubi.create.content.contraptions.components.structureMovement.sync.LimbSwingUpdatePacket;
@ -76,6 +77,7 @@ public enum AllPackets {
LIMBSWING_UPDATE(LimbSwingUpdatePacket.class, LimbSwingUpdatePacket::new),
MINECART_CONTROLLER(MinecartControllerUpdatePacket.class, MinecartControllerUpdatePacket::new),
FLUID_SPLASH(FluidSplashPacket.class, FluidSplashPacket::new),
CONTRAPTION_FLUID(ContraptionFluidPacket.class, ContraptionFluidPacket::new),
;

View file

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

View file

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

View file

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

View file

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

View file

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 432 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 822 B