Stalling for Storage

- Implemented Cargo Threshold and Idle Cargo schedule conditions
- Added a redstone link schedule condition
- Refactored wait conditions to share a ui builder with display links
- Added jei item assignment support to schedule conditions
- Fixed de-sync with ghost item slots in the schedule UI
This commit is contained in:
simibubi 2022-05-26 19:00:03 +02:00
parent 142e2f6dab
commit a1347799af
77 changed files with 1415 additions and 823 deletions

View file

@ -545,22 +545,22 @@ bf2b0310500213ff853c748c236eb5d01f61658e assets/create/blockstates/yellow_toolbo
7f39521b211441f5c3e06d60c5978cebe16cacfb assets/create/blockstates/zinc_block.json 7f39521b211441f5c3e06d60c5978cebe16cacfb assets/create/blockstates/zinc_block.json
b7181bcd8182b2f17088e5aa881f374c9c65470c assets/create/blockstates/zinc_ore.json b7181bcd8182b2f17088e5aa881f374c9c65470c assets/create/blockstates/zinc_ore.json
218909cbc3671e376253d8af1d930be6b1ad8988 assets/create/lang/en_ud.json 218909cbc3671e376253d8af1d930be6b1ad8988 assets/create/lang/en_ud.json
47eaa8bf35cecdd519345b64a4ea64f85a05cf4e assets/create/lang/en_us.json 7af05d7bfa02d5d934163adaf8371f1fcf53068a assets/create/lang/en_us.json
10c52355535ca985fc573090090f2ef635b69ded assets/create/lang/unfinished/de_de.json 24dbe3aa3e9e22c656d50097ead53f9af112d285 assets/create/lang/unfinished/de_de.json
b319f91f29cfa0610266ec04cf81d6bcb67655fe assets/create/lang/unfinished/es_cl.json 1de1a8de5098b9f9845d68052e6b9d286ac1c020 assets/create/lang/unfinished/es_cl.json
3e81086283e90d64cdf82acda4d2585fe8b47dd2 assets/create/lang/unfinished/es_es.json 35d245e95381fa08f20626110b46394d7e3445e1 assets/create/lang/unfinished/es_es.json
7cd6da27541e2bb9ec6d9254e8f5dcb4bd182d2c assets/create/lang/unfinished/fr_fr.json 1d78b91af73f68ae5bdafdce9f0529ce301e9893 assets/create/lang/unfinished/fr_fr.json
9eb92a896d3aff2ff09a705b02bf68bbf6a8143d assets/create/lang/unfinished/it_it.json b010715b2b4c9e3318e344d8632babeb0bdddd05 assets/create/lang/unfinished/it_it.json
6c4349c4964946b229bd9d4c159ceb5b32e9571a assets/create/lang/unfinished/ja_jp.json 416ef3123e544ac8bb077b5b681533466f4f46f0 assets/create/lang/unfinished/ja_jp.json
0a10d8eb065f0d857514d913bbe7c8b6f4c5a625 assets/create/lang/unfinished/ko_kr.json a6c3ebecdeaf46314c724a250eaa8d03bb421fac assets/create/lang/unfinished/ko_kr.json
579b19fc309057bd3c5d77783d2326be1f57b4cb assets/create/lang/unfinished/nl_nl.json 568753d777a591f1d4d6c0a423d39f1d0a38721a assets/create/lang/unfinished/nl_nl.json
aa1a27591572ef8bef422766dba95bd824b90ff1 assets/create/lang/unfinished/pl_pl.json 62fbe7e5a4ff03f88f839ac6bf6f7e3dd1264b6d assets/create/lang/unfinished/pl_pl.json
7efbd473e0aee14a439527706a2c40dbfc96b811 assets/create/lang/unfinished/pt_br.json d27addd2e8368e5814047b04dbe2f21649c5759d assets/create/lang/unfinished/pt_br.json
3f4c4cc0078717645bb9f844999e0d92e7ba5b02 assets/create/lang/unfinished/pt_pt.json 133931e124c31b7a718fe9e9ec6363c76be9a076 assets/create/lang/unfinished/pt_pt.json
f686b3e2df2feb232713545ff846b93f3e4fe45b assets/create/lang/unfinished/ro_ro.json 32d4d825ed84a8bdc38745aed0041a4136b48222 assets/create/lang/unfinished/ro_ro.json
95d8fe9d0744eda905dd2b7d6aa73203d8a3f82a assets/create/lang/unfinished/ru_ru.json d4a76cf509763bb0a937e69deccc54f6b0f8ed9b assets/create/lang/unfinished/ru_ru.json
23dea7cab680a529ec7689cc5bbfea1248dd59e5 assets/create/lang/unfinished/zh_cn.json 5184cf26d1f0792fac473d532d6d55c389f7b444 assets/create/lang/unfinished/zh_cn.json
ebba34f4159bb1f4437fa52b11bf73aea9945fb0 assets/create/lang/unfinished/zh_tw.json ee3afea45eaaea548b3d9fa29e004a56c08be50a assets/create/lang/unfinished/zh_tw.json
487a511a01b2a4531fb672f917922312db78f958 assets/create/models/block/acacia_window.json 487a511a01b2a4531fb672f917922312db78f958 assets/create/models/block/acacia_window.json
b48060cba1a382f373a05bf0039054053eccf076 assets/create/models/block/acacia_window_pane_noside.json b48060cba1a382f373a05bf0039054053eccf076 assets/create/models/block/acacia_window_pane_noside.json
3066db1bf03cffa1a9c7fbacf47ae586632f4eb3 assets/create/models/block/acacia_window_pane_noside_alt.json 3066db1bf03cffa1a9c7fbacf47ae586632f4eb3 assets/create/models/block/acacia_window_pane_noside_alt.json

View file

@ -1377,10 +1377,10 @@
"create.schedule.condition.time_of_day.digital_format": "%1$s:%3$s %4$s", "create.schedule.condition.time_of_day.digital_format": "%1$s:%3$s %4$s",
"create.schedule.condition.time_of_day.grace_period": "Grace Period", "create.schedule.condition.time_of_day.grace_period": "Grace Period",
"create.schedule.condition.time_of_day.grace_period.format": "+%1$s Hrs.", "create.schedule.condition.time_of_day.grace_period.format": "+%1$s Hrs.",
"create.schedule.condition.threshold.train_holds": "Train Holds %1$s", "create.schedule.condition.threshold.train_holds": "Train holds %1$s",
"create.schedule.condition.threshold.greater": "More than", "create.schedule.condition.threshold.greater": "more than",
"create.schedule.condition.threshold.less": "Less than", "create.schedule.condition.threshold.less": "less than",
"create.schedule.condition.threshold.equal": "Exactly", "create.schedule.condition.threshold.equal": "exactly",
"create.schedule.condition.threshold.x_units_of_item": "%1$s %2$s of %3$s", "create.schedule.condition.threshold.x_units_of_item": "%1$s %2$s of %3$s",
"create.schedule.condition.threshold.matching_content": "Matching Content", "create.schedule.condition.threshold.matching_content": "Matching Content",
"create.schedule.condition.threshold.item_measure": "Item Measure", "create.schedule.condition.threshold.item_measure": "Item Measure",
@ -1391,6 +1391,14 @@
"create.schedule.condition.threshold.place_item_2": "Filters can be used", "create.schedule.condition.threshold.place_item_2": "Filters can be used",
"create.schedule.condition.fluid_threshold": "Fluid Cargo Condition", "create.schedule.condition.fluid_threshold": "Fluid Cargo Condition",
"create.schedule.condition.item_threshold": "Item Cargo Condition", "create.schedule.condition.item_threshold": "Item Cargo Condition",
"create.schedule.condition.redstone_link": "Redstone Link",
"create.schedule.condition.redstone_link_on": "Link On",
"create.schedule.condition.redstone_link_off": "Link Off",
"create.schedule.condition.redstone_link.powered": "Powered",
"create.schedule.condition.redstone_link.unpowered": "Not powered",
"create.schedule.condition.redstone_link.frequency_state": "Frequency state:",
"create.schedule.condition.redstone_link.frequency_powered": "Frequency powered:",
"create.schedule.condition.redstone_link.frequency_unpowered": "Frequency not powered:",
"create.schedule.loop": "Loop Forever", "create.schedule.loop": "Loop Forever",
"create.schedule.loop1": "Schedule starts over", "create.schedule.loop1": "Schedule starts over",
"create.schedule.loop2": "when completed", "create.schedule.loop2": "when completed",

View file

@ -1,5 +1,5 @@
{ {
"_": "Missing Localizations: 919", "_": "Missing Localizations: 927",
"_": "->------------------------] Game Elements [------------------------<-", "_": "->------------------------] Game Elements [------------------------<-",
@ -1378,10 +1378,10 @@
"create.schedule.condition.time_of_day.digital_format": "UNLOCALIZED: %1$s:%3$s %4$s", "create.schedule.condition.time_of_day.digital_format": "UNLOCALIZED: %1$s:%3$s %4$s",
"create.schedule.condition.time_of_day.grace_period": "UNLOCALIZED: Grace Period", "create.schedule.condition.time_of_day.grace_period": "UNLOCALIZED: Grace Period",
"create.schedule.condition.time_of_day.grace_period.format": "UNLOCALIZED: +%1$s Hrs.", "create.schedule.condition.time_of_day.grace_period.format": "UNLOCALIZED: +%1$s Hrs.",
"create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train Holds %1$s", "create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train holds %1$s",
"create.schedule.condition.threshold.greater": "UNLOCALIZED: More than", "create.schedule.condition.threshold.greater": "UNLOCALIZED: more than",
"create.schedule.condition.threshold.less": "UNLOCALIZED: Less than", "create.schedule.condition.threshold.less": "UNLOCALIZED: less than",
"create.schedule.condition.threshold.equal": "UNLOCALIZED: Exactly", "create.schedule.condition.threshold.equal": "UNLOCALIZED: exactly",
"create.schedule.condition.threshold.x_units_of_item": "UNLOCALIZED: %1$s %2$s of %3$s", "create.schedule.condition.threshold.x_units_of_item": "UNLOCALIZED: %1$s %2$s of %3$s",
"create.schedule.condition.threshold.matching_content": "UNLOCALIZED: Matching Content", "create.schedule.condition.threshold.matching_content": "UNLOCALIZED: Matching Content",
"create.schedule.condition.threshold.item_measure": "UNLOCALIZED: Item Measure", "create.schedule.condition.threshold.item_measure": "UNLOCALIZED: Item Measure",
@ -1392,6 +1392,14 @@
"create.schedule.condition.threshold.place_item_2": "UNLOCALIZED: Filters can be used", "create.schedule.condition.threshold.place_item_2": "UNLOCALIZED: Filters can be used",
"create.schedule.condition.fluid_threshold": "UNLOCALIZED: Fluid Cargo Condition", "create.schedule.condition.fluid_threshold": "UNLOCALIZED: Fluid Cargo Condition",
"create.schedule.condition.item_threshold": "UNLOCALIZED: Item Cargo Condition", "create.schedule.condition.item_threshold": "UNLOCALIZED: Item Cargo Condition",
"create.schedule.condition.redstone_link": "UNLOCALIZED: Redstone Link",
"create.schedule.condition.redstone_link_on": "UNLOCALIZED: Link On",
"create.schedule.condition.redstone_link_off": "UNLOCALIZED: Link Off",
"create.schedule.condition.redstone_link.powered": "UNLOCALIZED: Powered",
"create.schedule.condition.redstone_link.unpowered": "UNLOCALIZED: Not powered",
"create.schedule.condition.redstone_link.frequency_state": "UNLOCALIZED: Frequency state:",
"create.schedule.condition.redstone_link.frequency_powered": "UNLOCALIZED: Frequency powered:",
"create.schedule.condition.redstone_link.frequency_unpowered": "UNLOCALIZED: Frequency not powered:",
"create.schedule.loop": "UNLOCALIZED: Loop Forever", "create.schedule.loop": "UNLOCALIZED: Loop Forever",
"create.schedule.loop1": "UNLOCALIZED: Schedule starts over", "create.schedule.loop1": "UNLOCALIZED: Schedule starts over",
"create.schedule.loop2": "UNLOCALIZED: when completed", "create.schedule.loop2": "UNLOCALIZED: when completed",

View file

@ -1,5 +1,5 @@
{ {
"_": "Missing Localizations: 569", "_": "Missing Localizations: 577",
"_": "->------------------------] Game Elements [------------------------<-", "_": "->------------------------] Game Elements [------------------------<-",
@ -1378,10 +1378,10 @@
"create.schedule.condition.time_of_day.digital_format": "UNLOCALIZED: %1$s:%3$s %4$s", "create.schedule.condition.time_of_day.digital_format": "UNLOCALIZED: %1$s:%3$s %4$s",
"create.schedule.condition.time_of_day.grace_period": "UNLOCALIZED: Grace Period", "create.schedule.condition.time_of_day.grace_period": "UNLOCALIZED: Grace Period",
"create.schedule.condition.time_of_day.grace_period.format": "UNLOCALIZED: +%1$s Hrs.", "create.schedule.condition.time_of_day.grace_period.format": "UNLOCALIZED: +%1$s Hrs.",
"create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train Holds %1$s", "create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train holds %1$s",
"create.schedule.condition.threshold.greater": "UNLOCALIZED: More than", "create.schedule.condition.threshold.greater": "UNLOCALIZED: more than",
"create.schedule.condition.threshold.less": "UNLOCALIZED: Less than", "create.schedule.condition.threshold.less": "UNLOCALIZED: less than",
"create.schedule.condition.threshold.equal": "UNLOCALIZED: Exactly", "create.schedule.condition.threshold.equal": "UNLOCALIZED: exactly",
"create.schedule.condition.threshold.x_units_of_item": "UNLOCALIZED: %1$s %2$s of %3$s", "create.schedule.condition.threshold.x_units_of_item": "UNLOCALIZED: %1$s %2$s of %3$s",
"create.schedule.condition.threshold.matching_content": "UNLOCALIZED: Matching Content", "create.schedule.condition.threshold.matching_content": "UNLOCALIZED: Matching Content",
"create.schedule.condition.threshold.item_measure": "UNLOCALIZED: Item Measure", "create.schedule.condition.threshold.item_measure": "UNLOCALIZED: Item Measure",
@ -1392,6 +1392,14 @@
"create.schedule.condition.threshold.place_item_2": "UNLOCALIZED: Filters can be used", "create.schedule.condition.threshold.place_item_2": "UNLOCALIZED: Filters can be used",
"create.schedule.condition.fluid_threshold": "UNLOCALIZED: Fluid Cargo Condition", "create.schedule.condition.fluid_threshold": "UNLOCALIZED: Fluid Cargo Condition",
"create.schedule.condition.item_threshold": "UNLOCALIZED: Item Cargo Condition", "create.schedule.condition.item_threshold": "UNLOCALIZED: Item Cargo Condition",
"create.schedule.condition.redstone_link": "UNLOCALIZED: Redstone Link",
"create.schedule.condition.redstone_link_on": "UNLOCALIZED: Link On",
"create.schedule.condition.redstone_link_off": "UNLOCALIZED: Link Off",
"create.schedule.condition.redstone_link.powered": "UNLOCALIZED: Powered",
"create.schedule.condition.redstone_link.unpowered": "UNLOCALIZED: Not powered",
"create.schedule.condition.redstone_link.frequency_state": "UNLOCALIZED: Frequency state:",
"create.schedule.condition.redstone_link.frequency_powered": "UNLOCALIZED: Frequency powered:",
"create.schedule.condition.redstone_link.frequency_unpowered": "UNLOCALIZED: Frequency not powered:",
"create.schedule.loop": "UNLOCALIZED: Loop Forever", "create.schedule.loop": "UNLOCALIZED: Loop Forever",
"create.schedule.loop1": "UNLOCALIZED: Schedule starts over", "create.schedule.loop1": "UNLOCALIZED: Schedule starts over",
"create.schedule.loop2": "UNLOCALIZED: when completed", "create.schedule.loop2": "UNLOCALIZED: when completed",

View file

@ -1,5 +1,5 @@
{ {
"_": "Missing Localizations: 233", "_": "Missing Localizations: 241",
"_": "->------------------------] Game Elements [------------------------<-", "_": "->------------------------] Game Elements [------------------------<-",
@ -1378,10 +1378,10 @@
"create.schedule.condition.time_of_day.digital_format": "UNLOCALIZED: %1$s:%3$s %4$s", "create.schedule.condition.time_of_day.digital_format": "UNLOCALIZED: %1$s:%3$s %4$s",
"create.schedule.condition.time_of_day.grace_period": "UNLOCALIZED: Grace Period", "create.schedule.condition.time_of_day.grace_period": "UNLOCALIZED: Grace Period",
"create.schedule.condition.time_of_day.grace_period.format": "UNLOCALIZED: +%1$s Hrs.", "create.schedule.condition.time_of_day.grace_period.format": "UNLOCALIZED: +%1$s Hrs.",
"create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train Holds %1$s", "create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train holds %1$s",
"create.schedule.condition.threshold.greater": "UNLOCALIZED: More than", "create.schedule.condition.threshold.greater": "UNLOCALIZED: more than",
"create.schedule.condition.threshold.less": "UNLOCALIZED: Less than", "create.schedule.condition.threshold.less": "UNLOCALIZED: less than",
"create.schedule.condition.threshold.equal": "UNLOCALIZED: Exactly", "create.schedule.condition.threshold.equal": "UNLOCALIZED: exactly",
"create.schedule.condition.threshold.x_units_of_item": "UNLOCALIZED: %1$s %2$s of %3$s", "create.schedule.condition.threshold.x_units_of_item": "UNLOCALIZED: %1$s %2$s of %3$s",
"create.schedule.condition.threshold.matching_content": "UNLOCALIZED: Matching Content", "create.schedule.condition.threshold.matching_content": "UNLOCALIZED: Matching Content",
"create.schedule.condition.threshold.item_measure": "UNLOCALIZED: Item Measure", "create.schedule.condition.threshold.item_measure": "UNLOCALIZED: Item Measure",
@ -1392,6 +1392,14 @@
"create.schedule.condition.threshold.place_item_2": "UNLOCALIZED: Filters can be used", "create.schedule.condition.threshold.place_item_2": "UNLOCALIZED: Filters can be used",
"create.schedule.condition.fluid_threshold": "UNLOCALIZED: Fluid Cargo Condition", "create.schedule.condition.fluid_threshold": "UNLOCALIZED: Fluid Cargo Condition",
"create.schedule.condition.item_threshold": "UNLOCALIZED: Item Cargo Condition", "create.schedule.condition.item_threshold": "UNLOCALIZED: Item Cargo Condition",
"create.schedule.condition.redstone_link": "UNLOCALIZED: Redstone Link",
"create.schedule.condition.redstone_link_on": "UNLOCALIZED: Link On",
"create.schedule.condition.redstone_link_off": "UNLOCALIZED: Link Off",
"create.schedule.condition.redstone_link.powered": "UNLOCALIZED: Powered",
"create.schedule.condition.redstone_link.unpowered": "UNLOCALIZED: Not powered",
"create.schedule.condition.redstone_link.frequency_state": "UNLOCALIZED: Frequency state:",
"create.schedule.condition.redstone_link.frequency_powered": "UNLOCALIZED: Frequency powered:",
"create.schedule.condition.redstone_link.frequency_unpowered": "UNLOCALIZED: Frequency not powered:",
"create.schedule.loop": "UNLOCALIZED: Loop Forever", "create.schedule.loop": "UNLOCALIZED: Loop Forever",
"create.schedule.loop1": "UNLOCALIZED: Schedule starts over", "create.schedule.loop1": "UNLOCALIZED: Schedule starts over",
"create.schedule.loop2": "UNLOCALIZED: when completed", "create.schedule.loop2": "UNLOCALIZED: when completed",

View file

@ -1,5 +1,5 @@
{ {
"_": "Missing Localizations: 1807", "_": "Missing Localizations: 1815",
"_": "->------------------------] Game Elements [------------------------<-", "_": "->------------------------] Game Elements [------------------------<-",
@ -1378,10 +1378,10 @@
"create.schedule.condition.time_of_day.digital_format": "UNLOCALIZED: %1$s:%3$s %4$s", "create.schedule.condition.time_of_day.digital_format": "UNLOCALIZED: %1$s:%3$s %4$s",
"create.schedule.condition.time_of_day.grace_period": "UNLOCALIZED: Grace Period", "create.schedule.condition.time_of_day.grace_period": "UNLOCALIZED: Grace Period",
"create.schedule.condition.time_of_day.grace_period.format": "UNLOCALIZED: +%1$s Hrs.", "create.schedule.condition.time_of_day.grace_period.format": "UNLOCALIZED: +%1$s Hrs.",
"create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train Holds %1$s", "create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train holds %1$s",
"create.schedule.condition.threshold.greater": "UNLOCALIZED: More than", "create.schedule.condition.threshold.greater": "UNLOCALIZED: more than",
"create.schedule.condition.threshold.less": "UNLOCALIZED: Less than", "create.schedule.condition.threshold.less": "UNLOCALIZED: less than",
"create.schedule.condition.threshold.equal": "UNLOCALIZED: Exactly", "create.schedule.condition.threshold.equal": "UNLOCALIZED: exactly",
"create.schedule.condition.threshold.x_units_of_item": "UNLOCALIZED: %1$s %2$s of %3$s", "create.schedule.condition.threshold.x_units_of_item": "UNLOCALIZED: %1$s %2$s of %3$s",
"create.schedule.condition.threshold.matching_content": "UNLOCALIZED: Matching Content", "create.schedule.condition.threshold.matching_content": "UNLOCALIZED: Matching Content",
"create.schedule.condition.threshold.item_measure": "UNLOCALIZED: Item Measure", "create.schedule.condition.threshold.item_measure": "UNLOCALIZED: Item Measure",
@ -1392,6 +1392,14 @@
"create.schedule.condition.threshold.place_item_2": "UNLOCALIZED: Filters can be used", "create.schedule.condition.threshold.place_item_2": "UNLOCALIZED: Filters can be used",
"create.schedule.condition.fluid_threshold": "UNLOCALIZED: Fluid Cargo Condition", "create.schedule.condition.fluid_threshold": "UNLOCALIZED: Fluid Cargo Condition",
"create.schedule.condition.item_threshold": "UNLOCALIZED: Item Cargo Condition", "create.schedule.condition.item_threshold": "UNLOCALIZED: Item Cargo Condition",
"create.schedule.condition.redstone_link": "UNLOCALIZED: Redstone Link",
"create.schedule.condition.redstone_link_on": "UNLOCALIZED: Link On",
"create.schedule.condition.redstone_link_off": "UNLOCALIZED: Link Off",
"create.schedule.condition.redstone_link.powered": "UNLOCALIZED: Powered",
"create.schedule.condition.redstone_link.unpowered": "UNLOCALIZED: Not powered",
"create.schedule.condition.redstone_link.frequency_state": "UNLOCALIZED: Frequency state:",
"create.schedule.condition.redstone_link.frequency_powered": "UNLOCALIZED: Frequency powered:",
"create.schedule.condition.redstone_link.frequency_unpowered": "UNLOCALIZED: Frequency not powered:",
"create.schedule.loop": "UNLOCALIZED: Loop Forever", "create.schedule.loop": "UNLOCALIZED: Loop Forever",
"create.schedule.loop1": "UNLOCALIZED: Schedule starts over", "create.schedule.loop1": "UNLOCALIZED: Schedule starts over",
"create.schedule.loop2": "UNLOCALIZED: when completed", "create.schedule.loop2": "UNLOCALIZED: when completed",

View file

@ -1,5 +1,5 @@
{ {
"_": "Missing Localizations: 1496", "_": "Missing Localizations: 1504",
"_": "->------------------------] Game Elements [------------------------<-", "_": "->------------------------] Game Elements [------------------------<-",
@ -1378,10 +1378,10 @@
"create.schedule.condition.time_of_day.digital_format": "UNLOCALIZED: %1$s:%3$s %4$s", "create.schedule.condition.time_of_day.digital_format": "UNLOCALIZED: %1$s:%3$s %4$s",
"create.schedule.condition.time_of_day.grace_period": "UNLOCALIZED: Grace Period", "create.schedule.condition.time_of_day.grace_period": "UNLOCALIZED: Grace Period",
"create.schedule.condition.time_of_day.grace_period.format": "UNLOCALIZED: +%1$s Hrs.", "create.schedule.condition.time_of_day.grace_period.format": "UNLOCALIZED: +%1$s Hrs.",
"create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train Holds %1$s", "create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train holds %1$s",
"create.schedule.condition.threshold.greater": "UNLOCALIZED: More than", "create.schedule.condition.threshold.greater": "UNLOCALIZED: more than",
"create.schedule.condition.threshold.less": "UNLOCALIZED: Less than", "create.schedule.condition.threshold.less": "UNLOCALIZED: less than",
"create.schedule.condition.threshold.equal": "UNLOCALIZED: Exactly", "create.schedule.condition.threshold.equal": "UNLOCALIZED: exactly",
"create.schedule.condition.threshold.x_units_of_item": "UNLOCALIZED: %1$s %2$s of %3$s", "create.schedule.condition.threshold.x_units_of_item": "UNLOCALIZED: %1$s %2$s of %3$s",
"create.schedule.condition.threshold.matching_content": "UNLOCALIZED: Matching Content", "create.schedule.condition.threshold.matching_content": "UNLOCALIZED: Matching Content",
"create.schedule.condition.threshold.item_measure": "UNLOCALIZED: Item Measure", "create.schedule.condition.threshold.item_measure": "UNLOCALIZED: Item Measure",
@ -1392,6 +1392,14 @@
"create.schedule.condition.threshold.place_item_2": "UNLOCALIZED: Filters can be used", "create.schedule.condition.threshold.place_item_2": "UNLOCALIZED: Filters can be used",
"create.schedule.condition.fluid_threshold": "UNLOCALIZED: Fluid Cargo Condition", "create.schedule.condition.fluid_threshold": "UNLOCALIZED: Fluid Cargo Condition",
"create.schedule.condition.item_threshold": "UNLOCALIZED: Item Cargo Condition", "create.schedule.condition.item_threshold": "UNLOCALIZED: Item Cargo Condition",
"create.schedule.condition.redstone_link": "UNLOCALIZED: Redstone Link",
"create.schedule.condition.redstone_link_on": "UNLOCALIZED: Link On",
"create.schedule.condition.redstone_link_off": "UNLOCALIZED: Link Off",
"create.schedule.condition.redstone_link.powered": "UNLOCALIZED: Powered",
"create.schedule.condition.redstone_link.unpowered": "UNLOCALIZED: Not powered",
"create.schedule.condition.redstone_link.frequency_state": "UNLOCALIZED: Frequency state:",
"create.schedule.condition.redstone_link.frequency_powered": "UNLOCALIZED: Frequency powered:",
"create.schedule.condition.redstone_link.frequency_unpowered": "UNLOCALIZED: Frequency not powered:",
"create.schedule.loop": "UNLOCALIZED: Loop Forever", "create.schedule.loop": "UNLOCALIZED: Loop Forever",
"create.schedule.loop1": "UNLOCALIZED: Schedule starts over", "create.schedule.loop1": "UNLOCALIZED: Schedule starts over",
"create.schedule.loop2": "UNLOCALIZED: when completed", "create.schedule.loop2": "UNLOCALIZED: when completed",

View file

@ -1,5 +1,5 @@
{ {
"_": "Missing Localizations: 235", "_": "Missing Localizations: 243",
"_": "->------------------------] Game Elements [------------------------<-", "_": "->------------------------] Game Elements [------------------------<-",
@ -1378,10 +1378,10 @@
"create.schedule.condition.time_of_day.digital_format": "UNLOCALIZED: %1$s:%3$s %4$s", "create.schedule.condition.time_of_day.digital_format": "UNLOCALIZED: %1$s:%3$s %4$s",
"create.schedule.condition.time_of_day.grace_period": "UNLOCALIZED: Grace Period", "create.schedule.condition.time_of_day.grace_period": "UNLOCALIZED: Grace Period",
"create.schedule.condition.time_of_day.grace_period.format": "UNLOCALIZED: +%1$s Hrs.", "create.schedule.condition.time_of_day.grace_period.format": "UNLOCALIZED: +%1$s Hrs.",
"create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train Holds %1$s", "create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train holds %1$s",
"create.schedule.condition.threshold.greater": "UNLOCALIZED: More than", "create.schedule.condition.threshold.greater": "UNLOCALIZED: more than",
"create.schedule.condition.threshold.less": "UNLOCALIZED: Less than", "create.schedule.condition.threshold.less": "UNLOCALIZED: less than",
"create.schedule.condition.threshold.equal": "UNLOCALIZED: Exactly", "create.schedule.condition.threshold.equal": "UNLOCALIZED: exactly",
"create.schedule.condition.threshold.x_units_of_item": "UNLOCALIZED: %1$s %2$s of %3$s", "create.schedule.condition.threshold.x_units_of_item": "UNLOCALIZED: %1$s %2$s of %3$s",
"create.schedule.condition.threshold.matching_content": "UNLOCALIZED: Matching Content", "create.schedule.condition.threshold.matching_content": "UNLOCALIZED: Matching Content",
"create.schedule.condition.threshold.item_measure": "UNLOCALIZED: Item Measure", "create.schedule.condition.threshold.item_measure": "UNLOCALIZED: Item Measure",
@ -1392,6 +1392,14 @@
"create.schedule.condition.threshold.place_item_2": "UNLOCALIZED: Filters can be used", "create.schedule.condition.threshold.place_item_2": "UNLOCALIZED: Filters can be used",
"create.schedule.condition.fluid_threshold": "UNLOCALIZED: Fluid Cargo Condition", "create.schedule.condition.fluid_threshold": "UNLOCALIZED: Fluid Cargo Condition",
"create.schedule.condition.item_threshold": "UNLOCALIZED: Item Cargo Condition", "create.schedule.condition.item_threshold": "UNLOCALIZED: Item Cargo Condition",
"create.schedule.condition.redstone_link": "UNLOCALIZED: Redstone Link",
"create.schedule.condition.redstone_link_on": "UNLOCALIZED: Link On",
"create.schedule.condition.redstone_link_off": "UNLOCALIZED: Link Off",
"create.schedule.condition.redstone_link.powered": "UNLOCALIZED: Powered",
"create.schedule.condition.redstone_link.unpowered": "UNLOCALIZED: Not powered",
"create.schedule.condition.redstone_link.frequency_state": "UNLOCALIZED: Frequency state:",
"create.schedule.condition.redstone_link.frequency_powered": "UNLOCALIZED: Frequency powered:",
"create.schedule.condition.redstone_link.frequency_unpowered": "UNLOCALIZED: Frequency not powered:",
"create.schedule.loop": "UNLOCALIZED: Loop Forever", "create.schedule.loop": "UNLOCALIZED: Loop Forever",
"create.schedule.loop1": "UNLOCALIZED: Schedule starts over", "create.schedule.loop1": "UNLOCALIZED: Schedule starts over",
"create.schedule.loop2": "UNLOCALIZED: when completed", "create.schedule.loop2": "UNLOCALIZED: when completed",

View file

@ -1,5 +1,5 @@
{ {
"_": "Missing Localizations: 235", "_": "Missing Localizations: 243",
"_": "->------------------------] Game Elements [------------------------<-", "_": "->------------------------] Game Elements [------------------------<-",
@ -1378,10 +1378,10 @@
"create.schedule.condition.time_of_day.digital_format": "UNLOCALIZED: %1$s:%3$s %4$s", "create.schedule.condition.time_of_day.digital_format": "UNLOCALIZED: %1$s:%3$s %4$s",
"create.schedule.condition.time_of_day.grace_period": "UNLOCALIZED: Grace Period", "create.schedule.condition.time_of_day.grace_period": "UNLOCALIZED: Grace Period",
"create.schedule.condition.time_of_day.grace_period.format": "UNLOCALIZED: +%1$s Hrs.", "create.schedule.condition.time_of_day.grace_period.format": "UNLOCALIZED: +%1$s Hrs.",
"create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train Holds %1$s", "create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train holds %1$s",
"create.schedule.condition.threshold.greater": "UNLOCALIZED: More than", "create.schedule.condition.threshold.greater": "UNLOCALIZED: more than",
"create.schedule.condition.threshold.less": "UNLOCALIZED: Less than", "create.schedule.condition.threshold.less": "UNLOCALIZED: less than",
"create.schedule.condition.threshold.equal": "UNLOCALIZED: Exactly", "create.schedule.condition.threshold.equal": "UNLOCALIZED: exactly",
"create.schedule.condition.threshold.x_units_of_item": "UNLOCALIZED: %1$s %2$s of %3$s", "create.schedule.condition.threshold.x_units_of_item": "UNLOCALIZED: %1$s %2$s of %3$s",
"create.schedule.condition.threshold.matching_content": "UNLOCALIZED: Matching Content", "create.schedule.condition.threshold.matching_content": "UNLOCALIZED: Matching Content",
"create.schedule.condition.threshold.item_measure": "UNLOCALIZED: Item Measure", "create.schedule.condition.threshold.item_measure": "UNLOCALIZED: Item Measure",
@ -1392,6 +1392,14 @@
"create.schedule.condition.threshold.place_item_2": "UNLOCALIZED: Filters can be used", "create.schedule.condition.threshold.place_item_2": "UNLOCALIZED: Filters can be used",
"create.schedule.condition.fluid_threshold": "UNLOCALIZED: Fluid Cargo Condition", "create.schedule.condition.fluid_threshold": "UNLOCALIZED: Fluid Cargo Condition",
"create.schedule.condition.item_threshold": "UNLOCALIZED: Item Cargo Condition", "create.schedule.condition.item_threshold": "UNLOCALIZED: Item Cargo Condition",
"create.schedule.condition.redstone_link": "UNLOCALIZED: Redstone Link",
"create.schedule.condition.redstone_link_on": "UNLOCALIZED: Link On",
"create.schedule.condition.redstone_link_off": "UNLOCALIZED: Link Off",
"create.schedule.condition.redstone_link.powered": "UNLOCALIZED: Powered",
"create.schedule.condition.redstone_link.unpowered": "UNLOCALIZED: Not powered",
"create.schedule.condition.redstone_link.frequency_state": "UNLOCALIZED: Frequency state:",
"create.schedule.condition.redstone_link.frequency_powered": "UNLOCALIZED: Frequency powered:",
"create.schedule.condition.redstone_link.frequency_unpowered": "UNLOCALIZED: Frequency not powered:",
"create.schedule.loop": "UNLOCALIZED: Loop Forever", "create.schedule.loop": "UNLOCALIZED: Loop Forever",
"create.schedule.loop1": "UNLOCALIZED: Schedule starts over", "create.schedule.loop1": "UNLOCALIZED: Schedule starts over",
"create.schedule.loop2": "UNLOCALIZED: when completed", "create.schedule.loop2": "UNLOCALIZED: when completed",

View file

@ -1,5 +1,5 @@
{ {
"_": "Missing Localizations: 2159", "_": "Missing Localizations: 2167",
"_": "->------------------------] Game Elements [------------------------<-", "_": "->------------------------] Game Elements [------------------------<-",
@ -1378,10 +1378,10 @@
"create.schedule.condition.time_of_day.digital_format": "UNLOCALIZED: %1$s:%3$s %4$s", "create.schedule.condition.time_of_day.digital_format": "UNLOCALIZED: %1$s:%3$s %4$s",
"create.schedule.condition.time_of_day.grace_period": "UNLOCALIZED: Grace Period", "create.schedule.condition.time_of_day.grace_period": "UNLOCALIZED: Grace Period",
"create.schedule.condition.time_of_day.grace_period.format": "UNLOCALIZED: +%1$s Hrs.", "create.schedule.condition.time_of_day.grace_period.format": "UNLOCALIZED: +%1$s Hrs.",
"create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train Holds %1$s", "create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train holds %1$s",
"create.schedule.condition.threshold.greater": "UNLOCALIZED: More than", "create.schedule.condition.threshold.greater": "UNLOCALIZED: more than",
"create.schedule.condition.threshold.less": "UNLOCALIZED: Less than", "create.schedule.condition.threshold.less": "UNLOCALIZED: less than",
"create.schedule.condition.threshold.equal": "UNLOCALIZED: Exactly", "create.schedule.condition.threshold.equal": "UNLOCALIZED: exactly",
"create.schedule.condition.threshold.x_units_of_item": "UNLOCALIZED: %1$s %2$s of %3$s", "create.schedule.condition.threshold.x_units_of_item": "UNLOCALIZED: %1$s %2$s of %3$s",
"create.schedule.condition.threshold.matching_content": "UNLOCALIZED: Matching Content", "create.schedule.condition.threshold.matching_content": "UNLOCALIZED: Matching Content",
"create.schedule.condition.threshold.item_measure": "UNLOCALIZED: Item Measure", "create.schedule.condition.threshold.item_measure": "UNLOCALIZED: Item Measure",
@ -1392,6 +1392,14 @@
"create.schedule.condition.threshold.place_item_2": "UNLOCALIZED: Filters can be used", "create.schedule.condition.threshold.place_item_2": "UNLOCALIZED: Filters can be used",
"create.schedule.condition.fluid_threshold": "UNLOCALIZED: Fluid Cargo Condition", "create.schedule.condition.fluid_threshold": "UNLOCALIZED: Fluid Cargo Condition",
"create.schedule.condition.item_threshold": "UNLOCALIZED: Item Cargo Condition", "create.schedule.condition.item_threshold": "UNLOCALIZED: Item Cargo Condition",
"create.schedule.condition.redstone_link": "UNLOCALIZED: Redstone Link",
"create.schedule.condition.redstone_link_on": "UNLOCALIZED: Link On",
"create.schedule.condition.redstone_link_off": "UNLOCALIZED: Link Off",
"create.schedule.condition.redstone_link.powered": "UNLOCALIZED: Powered",
"create.schedule.condition.redstone_link.unpowered": "UNLOCALIZED: Not powered",
"create.schedule.condition.redstone_link.frequency_state": "UNLOCALIZED: Frequency state:",
"create.schedule.condition.redstone_link.frequency_powered": "UNLOCALIZED: Frequency powered:",
"create.schedule.condition.redstone_link.frequency_unpowered": "UNLOCALIZED: Frequency not powered:",
"create.schedule.loop": "UNLOCALIZED: Loop Forever", "create.schedule.loop": "UNLOCALIZED: Loop Forever",
"create.schedule.loop1": "UNLOCALIZED: Schedule starts over", "create.schedule.loop1": "UNLOCALIZED: Schedule starts over",
"create.schedule.loop2": "UNLOCALIZED: when completed", "create.schedule.loop2": "UNLOCALIZED: when completed",

View file

@ -1,5 +1,5 @@
{ {
"_": "Missing Localizations: 608", "_": "Missing Localizations: 616",
"_": "->------------------------] Game Elements [------------------------<-", "_": "->------------------------] Game Elements [------------------------<-",
@ -1378,10 +1378,10 @@
"create.schedule.condition.time_of_day.digital_format": "UNLOCALIZED: %1$s:%3$s %4$s", "create.schedule.condition.time_of_day.digital_format": "UNLOCALIZED: %1$s:%3$s %4$s",
"create.schedule.condition.time_of_day.grace_period": "UNLOCALIZED: Grace Period", "create.schedule.condition.time_of_day.grace_period": "UNLOCALIZED: Grace Period",
"create.schedule.condition.time_of_day.grace_period.format": "UNLOCALIZED: +%1$s Hrs.", "create.schedule.condition.time_of_day.grace_period.format": "UNLOCALIZED: +%1$s Hrs.",
"create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train Holds %1$s", "create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train holds %1$s",
"create.schedule.condition.threshold.greater": "UNLOCALIZED: More than", "create.schedule.condition.threshold.greater": "UNLOCALIZED: more than",
"create.schedule.condition.threshold.less": "UNLOCALIZED: Less than", "create.schedule.condition.threshold.less": "UNLOCALIZED: less than",
"create.schedule.condition.threshold.equal": "UNLOCALIZED: Exactly", "create.schedule.condition.threshold.equal": "UNLOCALIZED: exactly",
"create.schedule.condition.threshold.x_units_of_item": "UNLOCALIZED: %1$s %2$s of %3$s", "create.schedule.condition.threshold.x_units_of_item": "UNLOCALIZED: %1$s %2$s of %3$s",
"create.schedule.condition.threshold.matching_content": "UNLOCALIZED: Matching Content", "create.schedule.condition.threshold.matching_content": "UNLOCALIZED: Matching Content",
"create.schedule.condition.threshold.item_measure": "UNLOCALIZED: Item Measure", "create.schedule.condition.threshold.item_measure": "UNLOCALIZED: Item Measure",
@ -1392,6 +1392,14 @@
"create.schedule.condition.threshold.place_item_2": "UNLOCALIZED: Filters can be used", "create.schedule.condition.threshold.place_item_2": "UNLOCALIZED: Filters can be used",
"create.schedule.condition.fluid_threshold": "UNLOCALIZED: Fluid Cargo Condition", "create.schedule.condition.fluid_threshold": "UNLOCALIZED: Fluid Cargo Condition",
"create.schedule.condition.item_threshold": "UNLOCALIZED: Item Cargo Condition", "create.schedule.condition.item_threshold": "UNLOCALIZED: Item Cargo Condition",
"create.schedule.condition.redstone_link": "UNLOCALIZED: Redstone Link",
"create.schedule.condition.redstone_link_on": "UNLOCALIZED: Link On",
"create.schedule.condition.redstone_link_off": "UNLOCALIZED: Link Off",
"create.schedule.condition.redstone_link.powered": "UNLOCALIZED: Powered",
"create.schedule.condition.redstone_link.unpowered": "UNLOCALIZED: Not powered",
"create.schedule.condition.redstone_link.frequency_state": "UNLOCALIZED: Frequency state:",
"create.schedule.condition.redstone_link.frequency_powered": "UNLOCALIZED: Frequency powered:",
"create.schedule.condition.redstone_link.frequency_unpowered": "UNLOCALIZED: Frequency not powered:",
"create.schedule.loop": "UNLOCALIZED: Loop Forever", "create.schedule.loop": "UNLOCALIZED: Loop Forever",
"create.schedule.loop1": "UNLOCALIZED: Schedule starts over", "create.schedule.loop1": "UNLOCALIZED: Schedule starts over",
"create.schedule.loop2": "UNLOCALIZED: when completed", "create.schedule.loop2": "UNLOCALIZED: when completed",

View file

@ -1,5 +1,5 @@
{ {
"_": "Missing Localizations: 1103", "_": "Missing Localizations: 1111",
"_": "->------------------------] Game Elements [------------------------<-", "_": "->------------------------] Game Elements [------------------------<-",
@ -1378,10 +1378,10 @@
"create.schedule.condition.time_of_day.digital_format": "UNLOCALIZED: %1$s:%3$s %4$s", "create.schedule.condition.time_of_day.digital_format": "UNLOCALIZED: %1$s:%3$s %4$s",
"create.schedule.condition.time_of_day.grace_period": "UNLOCALIZED: Grace Period", "create.schedule.condition.time_of_day.grace_period": "UNLOCALIZED: Grace Period",
"create.schedule.condition.time_of_day.grace_period.format": "UNLOCALIZED: +%1$s Hrs.", "create.schedule.condition.time_of_day.grace_period.format": "UNLOCALIZED: +%1$s Hrs.",
"create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train Holds %1$s", "create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train holds %1$s",
"create.schedule.condition.threshold.greater": "UNLOCALIZED: More than", "create.schedule.condition.threshold.greater": "UNLOCALIZED: more than",
"create.schedule.condition.threshold.less": "UNLOCALIZED: Less than", "create.schedule.condition.threshold.less": "UNLOCALIZED: less than",
"create.schedule.condition.threshold.equal": "UNLOCALIZED: Exactly", "create.schedule.condition.threshold.equal": "UNLOCALIZED: exactly",
"create.schedule.condition.threshold.x_units_of_item": "UNLOCALIZED: %1$s %2$s of %3$s", "create.schedule.condition.threshold.x_units_of_item": "UNLOCALIZED: %1$s %2$s of %3$s",
"create.schedule.condition.threshold.matching_content": "UNLOCALIZED: Matching Content", "create.schedule.condition.threshold.matching_content": "UNLOCALIZED: Matching Content",
"create.schedule.condition.threshold.item_measure": "UNLOCALIZED: Item Measure", "create.schedule.condition.threshold.item_measure": "UNLOCALIZED: Item Measure",
@ -1392,6 +1392,14 @@
"create.schedule.condition.threshold.place_item_2": "UNLOCALIZED: Filters can be used", "create.schedule.condition.threshold.place_item_2": "UNLOCALIZED: Filters can be used",
"create.schedule.condition.fluid_threshold": "UNLOCALIZED: Fluid Cargo Condition", "create.schedule.condition.fluid_threshold": "UNLOCALIZED: Fluid Cargo Condition",
"create.schedule.condition.item_threshold": "UNLOCALIZED: Item Cargo Condition", "create.schedule.condition.item_threshold": "UNLOCALIZED: Item Cargo Condition",
"create.schedule.condition.redstone_link": "UNLOCALIZED: Redstone Link",
"create.schedule.condition.redstone_link_on": "UNLOCALIZED: Link On",
"create.schedule.condition.redstone_link_off": "UNLOCALIZED: Link Off",
"create.schedule.condition.redstone_link.powered": "UNLOCALIZED: Powered",
"create.schedule.condition.redstone_link.unpowered": "UNLOCALIZED: Not powered",
"create.schedule.condition.redstone_link.frequency_state": "UNLOCALIZED: Frequency state:",
"create.schedule.condition.redstone_link.frequency_powered": "UNLOCALIZED: Frequency powered:",
"create.schedule.condition.redstone_link.frequency_unpowered": "UNLOCALIZED: Frequency not powered:",
"create.schedule.loop": "UNLOCALIZED: Loop Forever", "create.schedule.loop": "UNLOCALIZED: Loop Forever",
"create.schedule.loop1": "UNLOCALIZED: Schedule starts over", "create.schedule.loop1": "UNLOCALIZED: Schedule starts over",
"create.schedule.loop2": "UNLOCALIZED: when completed", "create.schedule.loop2": "UNLOCALIZED: when completed",

View file

@ -1,5 +1,5 @@
{ {
"_": "Missing Localizations: 1781", "_": "Missing Localizations: 1789",
"_": "->------------------------] Game Elements [------------------------<-", "_": "->------------------------] Game Elements [------------------------<-",
@ -1378,10 +1378,10 @@
"create.schedule.condition.time_of_day.digital_format": "UNLOCALIZED: %1$s:%3$s %4$s", "create.schedule.condition.time_of_day.digital_format": "UNLOCALIZED: %1$s:%3$s %4$s",
"create.schedule.condition.time_of_day.grace_period": "UNLOCALIZED: Grace Period", "create.schedule.condition.time_of_day.grace_period": "UNLOCALIZED: Grace Period",
"create.schedule.condition.time_of_day.grace_period.format": "UNLOCALIZED: +%1$s Hrs.", "create.schedule.condition.time_of_day.grace_period.format": "UNLOCALIZED: +%1$s Hrs.",
"create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train Holds %1$s", "create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train holds %1$s",
"create.schedule.condition.threshold.greater": "UNLOCALIZED: More than", "create.schedule.condition.threshold.greater": "UNLOCALIZED: more than",
"create.schedule.condition.threshold.less": "UNLOCALIZED: Less than", "create.schedule.condition.threshold.less": "UNLOCALIZED: less than",
"create.schedule.condition.threshold.equal": "UNLOCALIZED: Exactly", "create.schedule.condition.threshold.equal": "UNLOCALIZED: exactly",
"create.schedule.condition.threshold.x_units_of_item": "UNLOCALIZED: %1$s %2$s of %3$s", "create.schedule.condition.threshold.x_units_of_item": "UNLOCALIZED: %1$s %2$s of %3$s",
"create.schedule.condition.threshold.matching_content": "UNLOCALIZED: Matching Content", "create.schedule.condition.threshold.matching_content": "UNLOCALIZED: Matching Content",
"create.schedule.condition.threshold.item_measure": "UNLOCALIZED: Item Measure", "create.schedule.condition.threshold.item_measure": "UNLOCALIZED: Item Measure",
@ -1392,6 +1392,14 @@
"create.schedule.condition.threshold.place_item_2": "UNLOCALIZED: Filters can be used", "create.schedule.condition.threshold.place_item_2": "UNLOCALIZED: Filters can be used",
"create.schedule.condition.fluid_threshold": "UNLOCALIZED: Fluid Cargo Condition", "create.schedule.condition.fluid_threshold": "UNLOCALIZED: Fluid Cargo Condition",
"create.schedule.condition.item_threshold": "UNLOCALIZED: Item Cargo Condition", "create.schedule.condition.item_threshold": "UNLOCALIZED: Item Cargo Condition",
"create.schedule.condition.redstone_link": "UNLOCALIZED: Redstone Link",
"create.schedule.condition.redstone_link_on": "UNLOCALIZED: Link On",
"create.schedule.condition.redstone_link_off": "UNLOCALIZED: Link Off",
"create.schedule.condition.redstone_link.powered": "UNLOCALIZED: Powered",
"create.schedule.condition.redstone_link.unpowered": "UNLOCALIZED: Not powered",
"create.schedule.condition.redstone_link.frequency_state": "UNLOCALIZED: Frequency state:",
"create.schedule.condition.redstone_link.frequency_powered": "UNLOCALIZED: Frequency powered:",
"create.schedule.condition.redstone_link.frequency_unpowered": "UNLOCALIZED: Frequency not powered:",
"create.schedule.loop": "UNLOCALIZED: Loop Forever", "create.schedule.loop": "UNLOCALIZED: Loop Forever",
"create.schedule.loop1": "UNLOCALIZED: Schedule starts over", "create.schedule.loop1": "UNLOCALIZED: Schedule starts over",
"create.schedule.loop2": "UNLOCALIZED: when completed", "create.schedule.loop2": "UNLOCALIZED: when completed",

View file

@ -1,5 +1,5 @@
{ {
"_": "Missing Localizations: 236", "_": "Missing Localizations: 244",
"_": "->------------------------] Game Elements [------------------------<-", "_": "->------------------------] Game Elements [------------------------<-",
@ -1378,10 +1378,10 @@
"create.schedule.condition.time_of_day.digital_format": "UNLOCALIZED: %1$s:%3$s %4$s", "create.schedule.condition.time_of_day.digital_format": "UNLOCALIZED: %1$s:%3$s %4$s",
"create.schedule.condition.time_of_day.grace_period": "UNLOCALIZED: Grace Period", "create.schedule.condition.time_of_day.grace_period": "UNLOCALIZED: Grace Period",
"create.schedule.condition.time_of_day.grace_period.format": "UNLOCALIZED: +%1$s Hrs.", "create.schedule.condition.time_of_day.grace_period.format": "UNLOCALIZED: +%1$s Hrs.",
"create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train Holds %1$s", "create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train holds %1$s",
"create.schedule.condition.threshold.greater": "UNLOCALIZED: More than", "create.schedule.condition.threshold.greater": "UNLOCALIZED: more than",
"create.schedule.condition.threshold.less": "UNLOCALIZED: Less than", "create.schedule.condition.threshold.less": "UNLOCALIZED: less than",
"create.schedule.condition.threshold.equal": "UNLOCALIZED: Exactly", "create.schedule.condition.threshold.equal": "UNLOCALIZED: exactly",
"create.schedule.condition.threshold.x_units_of_item": "UNLOCALIZED: %1$s %2$s of %3$s", "create.schedule.condition.threshold.x_units_of_item": "UNLOCALIZED: %1$s %2$s of %3$s",
"create.schedule.condition.threshold.matching_content": "UNLOCALIZED: Matching Content", "create.schedule.condition.threshold.matching_content": "UNLOCALIZED: Matching Content",
"create.schedule.condition.threshold.item_measure": "UNLOCALIZED: Item Measure", "create.schedule.condition.threshold.item_measure": "UNLOCALIZED: Item Measure",
@ -1392,6 +1392,14 @@
"create.schedule.condition.threshold.place_item_2": "UNLOCALIZED: Filters can be used", "create.schedule.condition.threshold.place_item_2": "UNLOCALIZED: Filters can be used",
"create.schedule.condition.fluid_threshold": "UNLOCALIZED: Fluid Cargo Condition", "create.schedule.condition.fluid_threshold": "UNLOCALIZED: Fluid Cargo Condition",
"create.schedule.condition.item_threshold": "UNLOCALIZED: Item Cargo Condition", "create.schedule.condition.item_threshold": "UNLOCALIZED: Item Cargo Condition",
"create.schedule.condition.redstone_link": "UNLOCALIZED: Redstone Link",
"create.schedule.condition.redstone_link_on": "UNLOCALIZED: Link On",
"create.schedule.condition.redstone_link_off": "UNLOCALIZED: Link Off",
"create.schedule.condition.redstone_link.powered": "UNLOCALIZED: Powered",
"create.schedule.condition.redstone_link.unpowered": "UNLOCALIZED: Not powered",
"create.schedule.condition.redstone_link.frequency_state": "UNLOCALIZED: Frequency state:",
"create.schedule.condition.redstone_link.frequency_powered": "UNLOCALIZED: Frequency powered:",
"create.schedule.condition.redstone_link.frequency_unpowered": "UNLOCALIZED: Frequency not powered:",
"create.schedule.loop": "UNLOCALIZED: Loop Forever", "create.schedule.loop": "UNLOCALIZED: Loop Forever",
"create.schedule.loop1": "UNLOCALIZED: Schedule starts over", "create.schedule.loop1": "UNLOCALIZED: Schedule starts over",
"create.schedule.loop2": "UNLOCALIZED: when completed", "create.schedule.loop2": "UNLOCALIZED: when completed",

View file

@ -1,5 +1,5 @@
{ {
"_": "Missing Localizations: 613", "_": "Missing Localizations: 621",
"_": "->------------------------] Game Elements [------------------------<-", "_": "->------------------------] Game Elements [------------------------<-",
@ -1378,10 +1378,10 @@
"create.schedule.condition.time_of_day.digital_format": "UNLOCALIZED: %1$s:%3$s %4$s", "create.schedule.condition.time_of_day.digital_format": "UNLOCALIZED: %1$s:%3$s %4$s",
"create.schedule.condition.time_of_day.grace_period": "UNLOCALIZED: Grace Period", "create.schedule.condition.time_of_day.grace_period": "UNLOCALIZED: Grace Period",
"create.schedule.condition.time_of_day.grace_period.format": "UNLOCALIZED: +%1$s Hrs.", "create.schedule.condition.time_of_day.grace_period.format": "UNLOCALIZED: +%1$s Hrs.",
"create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train Holds %1$s", "create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train holds %1$s",
"create.schedule.condition.threshold.greater": "UNLOCALIZED: More than", "create.schedule.condition.threshold.greater": "UNLOCALIZED: more than",
"create.schedule.condition.threshold.less": "UNLOCALIZED: Less than", "create.schedule.condition.threshold.less": "UNLOCALIZED: less than",
"create.schedule.condition.threshold.equal": "UNLOCALIZED: Exactly", "create.schedule.condition.threshold.equal": "UNLOCALIZED: exactly",
"create.schedule.condition.threshold.x_units_of_item": "UNLOCALIZED: %1$s %2$s of %3$s", "create.schedule.condition.threshold.x_units_of_item": "UNLOCALIZED: %1$s %2$s of %3$s",
"create.schedule.condition.threshold.matching_content": "UNLOCALIZED: Matching Content", "create.schedule.condition.threshold.matching_content": "UNLOCALIZED: Matching Content",
"create.schedule.condition.threshold.item_measure": "UNLOCALIZED: Item Measure", "create.schedule.condition.threshold.item_measure": "UNLOCALIZED: Item Measure",
@ -1392,6 +1392,14 @@
"create.schedule.condition.threshold.place_item_2": "UNLOCALIZED: Filters can be used", "create.schedule.condition.threshold.place_item_2": "UNLOCALIZED: Filters can be used",
"create.schedule.condition.fluid_threshold": "UNLOCALIZED: Fluid Cargo Condition", "create.schedule.condition.fluid_threshold": "UNLOCALIZED: Fluid Cargo Condition",
"create.schedule.condition.item_threshold": "UNLOCALIZED: Item Cargo Condition", "create.schedule.condition.item_threshold": "UNLOCALIZED: Item Cargo Condition",
"create.schedule.condition.redstone_link": "UNLOCALIZED: Redstone Link",
"create.schedule.condition.redstone_link_on": "UNLOCALIZED: Link On",
"create.schedule.condition.redstone_link_off": "UNLOCALIZED: Link Off",
"create.schedule.condition.redstone_link.powered": "UNLOCALIZED: Powered",
"create.schedule.condition.redstone_link.unpowered": "UNLOCALIZED: Not powered",
"create.schedule.condition.redstone_link.frequency_state": "UNLOCALIZED: Frequency state:",
"create.schedule.condition.redstone_link.frequency_powered": "UNLOCALIZED: Frequency powered:",
"create.schedule.condition.redstone_link.frequency_unpowered": "UNLOCALIZED: Frequency not powered:",
"create.schedule.loop": "UNLOCALIZED: Loop Forever", "create.schedule.loop": "UNLOCALIZED: Loop Forever",
"create.schedule.loop1": "UNLOCALIZED: Schedule starts over", "create.schedule.loop1": "UNLOCALIZED: Schedule starts over",
"create.schedule.loop2": "UNLOCALIZED: when completed", "create.schedule.loop2": "UNLOCALIZED: when completed",

View file

@ -1,5 +1,5 @@
{ {
"_": "Missing Localizations: 233", "_": "Missing Localizations: 241",
"_": "->------------------------] Game Elements [------------------------<-", "_": "->------------------------] Game Elements [------------------------<-",
@ -1378,10 +1378,10 @@
"create.schedule.condition.time_of_day.digital_format": "UNLOCALIZED: %1$s:%3$s %4$s", "create.schedule.condition.time_of_day.digital_format": "UNLOCALIZED: %1$s:%3$s %4$s",
"create.schedule.condition.time_of_day.grace_period": "UNLOCALIZED: Grace Period", "create.schedule.condition.time_of_day.grace_period": "UNLOCALIZED: Grace Period",
"create.schedule.condition.time_of_day.grace_period.format": "UNLOCALIZED: +%1$s Hrs.", "create.schedule.condition.time_of_day.grace_period.format": "UNLOCALIZED: +%1$s Hrs.",
"create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train Holds %1$s", "create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train holds %1$s",
"create.schedule.condition.threshold.greater": "UNLOCALIZED: More than", "create.schedule.condition.threshold.greater": "UNLOCALIZED: more than",
"create.schedule.condition.threshold.less": "UNLOCALIZED: Less than", "create.schedule.condition.threshold.less": "UNLOCALIZED: less than",
"create.schedule.condition.threshold.equal": "UNLOCALIZED: Exactly", "create.schedule.condition.threshold.equal": "UNLOCALIZED: exactly",
"create.schedule.condition.threshold.x_units_of_item": "UNLOCALIZED: %1$s %2$s of %3$s", "create.schedule.condition.threshold.x_units_of_item": "UNLOCALIZED: %1$s %2$s of %3$s",
"create.schedule.condition.threshold.matching_content": "UNLOCALIZED: Matching Content", "create.schedule.condition.threshold.matching_content": "UNLOCALIZED: Matching Content",
"create.schedule.condition.threshold.item_measure": "UNLOCALIZED: Item Measure", "create.schedule.condition.threshold.item_measure": "UNLOCALIZED: Item Measure",
@ -1392,6 +1392,14 @@
"create.schedule.condition.threshold.place_item_2": "UNLOCALIZED: Filters can be used", "create.schedule.condition.threshold.place_item_2": "UNLOCALIZED: Filters can be used",
"create.schedule.condition.fluid_threshold": "UNLOCALIZED: Fluid Cargo Condition", "create.schedule.condition.fluid_threshold": "UNLOCALIZED: Fluid Cargo Condition",
"create.schedule.condition.item_threshold": "UNLOCALIZED: Item Cargo Condition", "create.schedule.condition.item_threshold": "UNLOCALIZED: Item Cargo Condition",
"create.schedule.condition.redstone_link": "UNLOCALIZED: Redstone Link",
"create.schedule.condition.redstone_link_on": "UNLOCALIZED: Link On",
"create.schedule.condition.redstone_link_off": "UNLOCALIZED: Link Off",
"create.schedule.condition.redstone_link.powered": "UNLOCALIZED: Powered",
"create.schedule.condition.redstone_link.unpowered": "UNLOCALIZED: Not powered",
"create.schedule.condition.redstone_link.frequency_state": "UNLOCALIZED: Frequency state:",
"create.schedule.condition.redstone_link.frequency_powered": "UNLOCALIZED: Frequency powered:",
"create.schedule.condition.redstone_link.frequency_unpowered": "UNLOCALIZED: Frequency not powered:",
"create.schedule.loop": "UNLOCALIZED: Loop Forever", "create.schedule.loop": "UNLOCALIZED: Loop Forever",
"create.schedule.loop1": "UNLOCALIZED: Schedule starts over", "create.schedule.loop1": "UNLOCALIZED: Schedule starts over",
"create.schedule.loop2": "UNLOCALIZED: when completed", "create.schedule.loop2": "UNLOCALIZED: when completed",

View file

@ -1,5 +1,5 @@
{ {
"_": "Missing Localizations: 627", "_": "Missing Localizations: 635",
"_": "->------------------------] Game Elements [------------------------<-", "_": "->------------------------] Game Elements [------------------------<-",
@ -1378,10 +1378,10 @@
"create.schedule.condition.time_of_day.digital_format": "UNLOCALIZED: %1$s:%3$s %4$s", "create.schedule.condition.time_of_day.digital_format": "UNLOCALIZED: %1$s:%3$s %4$s",
"create.schedule.condition.time_of_day.grace_period": "UNLOCALIZED: Grace Period", "create.schedule.condition.time_of_day.grace_period": "UNLOCALIZED: Grace Period",
"create.schedule.condition.time_of_day.grace_period.format": "UNLOCALIZED: +%1$s Hrs.", "create.schedule.condition.time_of_day.grace_period.format": "UNLOCALIZED: +%1$s Hrs.",
"create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train Holds %1$s", "create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train holds %1$s",
"create.schedule.condition.threshold.greater": "UNLOCALIZED: More than", "create.schedule.condition.threshold.greater": "UNLOCALIZED: more than",
"create.schedule.condition.threshold.less": "UNLOCALIZED: Less than", "create.schedule.condition.threshold.less": "UNLOCALIZED: less than",
"create.schedule.condition.threshold.equal": "UNLOCALIZED: Exactly", "create.schedule.condition.threshold.equal": "UNLOCALIZED: exactly",
"create.schedule.condition.threshold.x_units_of_item": "UNLOCALIZED: %1$s %2$s of %3$s", "create.schedule.condition.threshold.x_units_of_item": "UNLOCALIZED: %1$s %2$s of %3$s",
"create.schedule.condition.threshold.matching_content": "UNLOCALIZED: Matching Content", "create.schedule.condition.threshold.matching_content": "UNLOCALIZED: Matching Content",
"create.schedule.condition.threshold.item_measure": "UNLOCALIZED: Item Measure", "create.schedule.condition.threshold.item_measure": "UNLOCALIZED: Item Measure",
@ -1392,6 +1392,14 @@
"create.schedule.condition.threshold.place_item_2": "UNLOCALIZED: Filters can be used", "create.schedule.condition.threshold.place_item_2": "UNLOCALIZED: Filters can be used",
"create.schedule.condition.fluid_threshold": "UNLOCALIZED: Fluid Cargo Condition", "create.schedule.condition.fluid_threshold": "UNLOCALIZED: Fluid Cargo Condition",
"create.schedule.condition.item_threshold": "UNLOCALIZED: Item Cargo Condition", "create.schedule.condition.item_threshold": "UNLOCALIZED: Item Cargo Condition",
"create.schedule.condition.redstone_link": "UNLOCALIZED: Redstone Link",
"create.schedule.condition.redstone_link_on": "UNLOCALIZED: Link On",
"create.schedule.condition.redstone_link_off": "UNLOCALIZED: Link Off",
"create.schedule.condition.redstone_link.powered": "UNLOCALIZED: Powered",
"create.schedule.condition.redstone_link.unpowered": "UNLOCALIZED: Not powered",
"create.schedule.condition.redstone_link.frequency_state": "UNLOCALIZED: Frequency state:",
"create.schedule.condition.redstone_link.frequency_powered": "UNLOCALIZED: Frequency powered:",
"create.schedule.condition.redstone_link.frequency_unpowered": "UNLOCALIZED: Frequency not powered:",
"create.schedule.loop": "UNLOCALIZED: Loop Forever", "create.schedule.loop": "UNLOCALIZED: Loop Forever",
"create.schedule.loop1": "UNLOCALIZED: Schedule starts over", "create.schedule.loop1": "UNLOCALIZED: Schedule starts over",
"create.schedule.loop2": "UNLOCALIZED: when completed", "create.schedule.loop2": "UNLOCALIZED: when completed",

View file

@ -51,6 +51,7 @@ import com.simibubi.create.content.contraptions.processing.BasinRecipe;
import com.simibubi.create.content.curiosities.tools.BlueprintScreen; import com.simibubi.create.content.curiosities.tools.BlueprintScreen;
import com.simibubi.create.content.logistics.item.LinkedControllerScreen; import com.simibubi.create.content.logistics.item.LinkedControllerScreen;
import com.simibubi.create.content.logistics.item.filter.AbstractFilterScreen; import com.simibubi.create.content.logistics.item.filter.AbstractFilterScreen;
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleScreen;
import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.config.CRecipes; import com.simibubi.create.foundation.config.CRecipes;
import com.simibubi.create.foundation.config.ConfigBase.ConfigBool; import com.simibubi.create.foundation.config.ConfigBase.ConfigBool;
@ -290,6 +291,7 @@ public class CreateJEI implements IModPlugin {
registration.addGhostIngredientHandler(AbstractFilterScreen.class, new GhostIngredientHandler()); registration.addGhostIngredientHandler(AbstractFilterScreen.class, new GhostIngredientHandler());
registration.addGhostIngredientHandler(BlueprintScreen.class, new GhostIngredientHandler()); registration.addGhostIngredientHandler(BlueprintScreen.class, new GhostIngredientHandler());
registration.addGhostIngredientHandler(LinkedControllerScreen.class, new GhostIngredientHandler()); registration.addGhostIngredientHandler(LinkedControllerScreen.class, new GhostIngredientHandler());
registration.addGhostIngredientHandler(ScheduleScreen.class, new GhostIngredientHandler());
} }
private class CategoryBuilder<T extends Recipe<?>> { private class CategoryBuilder<T extends Recipe<?>> {

View file

@ -20,7 +20,7 @@ import net.minecraft.world.item.ItemStack;
@MethodsReturnNonnullByDefault @MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault @ParametersAreNonnullByDefault
public class GhostIngredientHandler<T extends GhostItemContainer<?>> public class GhostIngredientHandler<T extends GhostItemContainer<?>>
implements IGhostIngredientHandler<AbstractSimiContainerScreen<T>> { implements IGhostIngredientHandler<AbstractSimiContainerScreen<T>> {
@Override @Override
public <I> List<Target<I>> getTargets(AbstractSimiContainerScreen<T> gui, I ingredient, boolean doStart) { public <I> List<Target<I>> getTargets(AbstractSimiContainerScreen<T> gui, I ingredient, boolean doStart) {
@ -29,9 +29,12 @@ public class GhostIngredientHandler<T extends GhostItemContainer<?>>
if (ingredient instanceof ItemStack) { if (ingredient instanceof ItemStack) {
for (int i = 36; i < gui.getMenu().slots.size(); i++) { for (int i = 36; i < gui.getMenu().slots.size(); i++) {
targets.add(new GhostTarget<>(gui, i - 36, isAttributeFilter)); if (gui.getMenu().slots.get(i)
.isActive())
targets.add(new GhostTarget<>(gui, i - 36, isAttributeFilter));
// Only accept items in 1st slot. 2nd is used for functionality, don't wanna override that one // Only accept items in 1st slot. 2nd is used for functionality, don't wanna
// override that one
if (isAttributeFilter) if (isAttributeFilter)
break; break;
} }
@ -41,8 +44,7 @@ public class GhostIngredientHandler<T extends GhostItemContainer<?>>
} }
@Override @Override
public void onComplete() { public void onComplete() {}
}
@Override @Override
public boolean shouldHighlightTargets() { public boolean shouldHighlightTargets() {

View file

@ -297,7 +297,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit
if (!initialized) if (!initialized)
contraptionInitialize(); contraptionInitialize();
contraption.storage.entityTick(this); contraption.tickStorage(this);
tickContraption(); tickContraption();
super.tick(); super.tick();

View file

@ -1290,4 +1290,8 @@ public abstract class Contraption {
} }
} }
public void tickStorage(AbstractContraptionEntity entity) {
storage.entityTick(entity);
}
} }

View file

@ -30,11 +30,11 @@ import net.minecraftforge.items.IItemHandlerModifiable;
public class MountedStorageManager { public class MountedStorageManager {
private ContraptionInvWrapper inventory; protected ContraptionInvWrapper inventory;
private ContraptionInvWrapper fuelInventory; protected ContraptionInvWrapper fuelInventory;
private CombinedTankWrapper fluidInventory; protected CombinedTankWrapper fluidInventory;
private Map<BlockPos, MountedStorage> storage; protected Map<BlockPos, MountedStorage> storage;
private Map<BlockPos, MountedFluidStorage> fluidStorage; protected Map<BlockPos, MountedFluidStorage> fluidStorage;
public MountedStorageManager() { public MountedStorageManager() {
storage = new HashMap<>(); storage = new HashMap<>();
@ -48,27 +48,29 @@ public class MountedStorageManager {
public void createHandlers() { public void createHandlers() {
Collection<MountedStorage> itemHandlers = storage.values(); Collection<MountedStorage> itemHandlers = storage.values();
inventory = wrap(itemHandlers.stream() inventory = wrapItems(itemHandlers.stream()
.map(MountedStorage::getItemHandler) .map(MountedStorage::getItemHandler)
.toList()); .toList(), false);
fuelInventory = wrap(itemHandlers.stream() fuelInventory = wrapItems(itemHandlers.stream()
.filter(MountedStorage::canUseForFuel) .filter(MountedStorage::canUseForFuel)
.map(MountedStorage::getItemHandler) .map(MountedStorage::getItemHandler)
.toList()); .toList(), true);
List<IFluidHandler> fluidHandlers = fluidStorage.values() fluidInventory = wrapFluids(fluidStorage.values()
.stream() .stream()
.map(MountedFluidStorage::getFluidHandler) .map(MountedFluidStorage::getFluidHandler)
.collect(Collectors.toList()); .collect(Collectors.toList()));
fluidInventory = new CombinedTankWrapper(
Arrays.copyOf(fluidHandlers.toArray(), fluidHandlers.size(), IFluidHandler[].class));
} }
private ContraptionInvWrapper wrap(List<IItemHandlerModifiable> list) { protected ContraptionInvWrapper wrapItems(Collection<IItemHandlerModifiable> list, boolean fuel) {
return new ContraptionInvWrapper(Arrays.copyOf(list.toArray(), list.size(), IItemHandlerModifiable[].class)); return new ContraptionInvWrapper(Arrays.copyOf(list.toArray(), list.size(), IItemHandlerModifiable[].class));
} }
protected CombinedTankWrapper wrapFluids(Collection<IFluidHandler> list) {
return new CombinedTankWrapper(Arrays.copyOf(list.toArray(), list.size(), IFluidHandler[].class));
}
public void addBlock(BlockPos localPos, BlockEntity te) { public void addBlock(BlockPos localPos, BlockEntity te) {
if (te != null && MountedStorage.canUseAsStorage(te)) if (te != null && MountedStorage.canUseAsStorage(te))
storage.put(localPos, new MountedStorage(te)); storage.put(localPos, new MountedStorage(te));
@ -86,18 +88,7 @@ public class MountedStorageManager {
.put(NbtUtils.readBlockPos(c.getCompound("Pos")), MountedFluidStorage.deserialize(c.getCompound("Data")))); .put(NbtUtils.readBlockPos(c.getCompound("Pos")), MountedFluidStorage.deserialize(c.getCompound("Data"))));
if (clientPacket && presentTileEntities != null) if (clientPacket && presentTileEntities != null)
fluidStorage.forEach((pos, mfs) -> { bindTanks(presentTileEntities);
BlockEntity tileEntity = presentTileEntities.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()
.startWithValue(tank.getFillState());
mfs.assignTileEntity(tank);
});
List<IItemHandlerModifiable> handlers = new ArrayList<>(); List<IItemHandlerModifiable> handlers = new ArrayList<>();
List<IItemHandlerModifiable> fuelHandlers = new ArrayList<>(); List<IItemHandlerModifiable> fuelHandlers = new ArrayList<>();
@ -108,14 +99,27 @@ public class MountedStorageManager {
fuelHandlers.add(itemHandler); fuelHandlers.add(itemHandler);
} }
int index = 0; inventory = wrapItems(handlers, false);
IFluidHandler[] fluidHandlers = new IFluidHandler[fluidStorage.size()]; fuelInventory = wrapItems(fuelHandlers, true);
for (MountedFluidStorage mountedStorage : fluidStorage.values()) fluidInventory = wrapFluids(fluidStorage.values()
fluidHandlers[index++] = mountedStorage.getFluidHandler(); .stream()
.map(MountedFluidStorage::getFluidHandler)
.toList());
}
inventory = wrap(handlers); public void bindTanks(Map<BlockPos, BlockEntity> presentTileEntities) {
fuelInventory = wrap(fuelHandlers); fluidStorage.forEach((pos, mfs) -> {
fluidInventory = new CombinedTankWrapper(fluidHandlers); BlockEntity tileEntity = presentTileEntities.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()
.startWithValue(tank.getFillState());
mfs.assignTileEntity(tank);
});
} }
public void write(CompoundTag nbt, boolean clientPacket) { public void write(CompoundTag nbt, boolean clientPacket) {

View file

@ -0,0 +1,143 @@
package com.simibubi.create.content.contraptions.components.structureMovement.train;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption.ContraptionInvWrapper;
import com.simibubi.create.content.contraptions.components.structureMovement.MountedStorageManager;
import com.simibubi.create.foundation.fluid.CombinedTankWrapper;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.items.IItemHandlerModifiable;
public class TrainCargoManager extends MountedStorageManager {
int ticksSinceLastExchange;
AtomicInteger version;
public TrainCargoManager() {
version = new AtomicInteger();
ticksSinceLastExchange = 0;
}
@Override
public void createHandlers() {
super.createHandlers();
}
@Override
protected ContraptionInvWrapper wrapItems(Collection<IItemHandlerModifiable> list, boolean fuel) {
if (fuel)
return super.wrapItems(list, fuel);
return new CargoInvWrapper(Arrays.copyOf(list.toArray(), list.size(), IItemHandlerModifiable[].class));
}
@Override
protected CombinedTankWrapper wrapFluids(Collection<IFluidHandler> list) {
return new CargoTankWrapper(Arrays.copyOf(list.toArray(), list.size(), IFluidHandler[].class));
}
@Override
public void write(CompoundTag nbt, boolean clientPacket) {
super.write(nbt, clientPacket);
nbt.putInt("TicksSinceLastExchange", ticksSinceLastExchange);
}
@Override
public void read(CompoundTag nbt, Map<BlockPos, BlockEntity> presentTileEntities, boolean clientPacket) {
super.read(nbt, presentTileEntities, clientPacket);
ticksSinceLastExchange = nbt.getInt("TicksSinceLastExchange");
}
public void resetIdleCargoTracker() {
ticksSinceLastExchange = 0;
}
public void tickIdleCargoTracker() {
ticksSinceLastExchange++;
}
public int getTicksSinceLastExchange() {
return ticksSinceLastExchange;
}
public int getVersion() {
return version.get();
}
void changeDetected() {
version.incrementAndGet();
resetIdleCargoTracker();
}
class CargoInvWrapper extends ContraptionInvWrapper {
public CargoInvWrapper(IItemHandlerModifiable... itemHandler) {
super(false, itemHandler);
}
@Override
public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) {
ItemStack remainder = super.insertItem(slot, stack, simulate);
if (!simulate && stack.getCount() != remainder.getCount())
changeDetected();
return remainder;
}
@Override
public ItemStack extractItem(int slot, int amount, boolean simulate) {
ItemStack extracted = super.extractItem(slot, amount, simulate);
if (!simulate && !extracted.isEmpty())
changeDetected();
return extracted;
}
@Override
public void setStackInSlot(int slot, ItemStack stack) {
if (!stack.equals(getStackInSlot(slot)))
changeDetected();
super.setStackInSlot(slot, stack);
}
}
class CargoTankWrapper extends CombinedTankWrapper {
public CargoTankWrapper(IFluidHandler... fluidHandler) {
super(fluidHandler);
}
@Override
public int fill(FluidStack resource, FluidAction action) {
int filled = super.fill(resource, action);
if (action.execute() && filled > 0)
changeDetected();
return filled;
}
@Override
public FluidStack drain(FluidStack resource, FluidAction action) {
FluidStack drained = super.drain(resource, action);
if (action.execute() && !drained.isEmpty())
changeDetected();
return drained;
}
@Override
public FluidStack drain(int maxDrain, FluidAction action) {
FluidStack drained = super.drain(maxDrain, action);
if (action.execute() && !drained.isEmpty())
changeDetected();
return drained;
}
}
}

View file

@ -1,8 +1,7 @@
package com.simibubi.create.content.logistics; package com.simibubi.create.content.logistics;
import org.apache.commons.lang3.tuple.Pair;
import com.simibubi.create.content.logistics.RedstoneLinkNetworkHandler.Frequency; import com.simibubi.create.content.logistics.RedstoneLinkNetworkHandler.Frequency;
import com.simibubi.create.foundation.utility.Couple;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
@ -16,7 +15,7 @@ public interface IRedstoneLinkable {
public boolean isAlive(); public boolean isAlive();
public Pair<Frequency, Frequency> getNetworkKey(); public Couple<Frequency> getNetworkKey();
public BlockPos getLocation(); public BlockPos getLocation();

View file

@ -6,12 +6,12 @@ import java.util.Iterator;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.commons.lang3.tuple.Pair;
import com.simibubi.create.Create; import com.simibubi.create.Create;
import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.tileEntity.behaviour.linked.LinkBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.linked.LinkBehaviour;
import com.simibubi.create.foundation.utility.Couple;
import com.simibubi.create.foundation.utility.WorldHelper; import com.simibubi.create.foundation.utility.WorldHelper;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
@ -21,8 +21,10 @@ import net.minecraft.world.level.LevelAccessor;
public class RedstoneLinkNetworkHandler { public class RedstoneLinkNetworkHandler {
static final Map<LevelAccessor, Map<Pair<Frequency, Frequency>, Set<IRedstoneLinkable>>> connections = static final Map<LevelAccessor, Map<Couple<Frequency>, Set<IRedstoneLinkable>>> connections =
new IdentityHashMap<>(); new IdentityHashMap<>();
public final AtomicInteger globalPowerVersion = new AtomicInteger();
public static class Frequency { public static class Frequency {
public static final Frequency EMPTY = new Frequency(ItemStack.EMPTY); public static final Frequency EMPTY = new Frequency(ItemStack.EMPTY);
@ -76,8 +78,8 @@ public class RedstoneLinkNetworkHandler {
} }
public Set<IRedstoneLinkable> getNetworkOf(LevelAccessor world, IRedstoneLinkable actor) { public Set<IRedstoneLinkable> getNetworkOf(LevelAccessor world, IRedstoneLinkable actor) {
Map<Pair<Frequency, Frequency>, Set<IRedstoneLinkable>> networksInWorld = networksIn(world); Map<Couple<Frequency>, Set<IRedstoneLinkable>> networksInWorld = networksIn(world);
Pair<Frequency, Frequency> key = actor.getNetworkKey(); Couple<Frequency> key = actor.getNetworkKey();
if (!networksInWorld.containsKey(key)) if (!networksInWorld.containsKey(key))
networksInWorld.put(key, new LinkedHashSet<>()); networksInWorld.put(key, new LinkedHashSet<>());
return networksInWorld.get(key); return networksInWorld.get(key);
@ -100,6 +102,7 @@ public class RedstoneLinkNetworkHandler {
public void updateNetworkOf(LevelAccessor world, IRedstoneLinkable actor) { public void updateNetworkOf(LevelAccessor world, IRedstoneLinkable actor) {
Set<IRedstoneLinkable> network = getNetworkOf(world, actor); Set<IRedstoneLinkable> network = getNetworkOf(world, actor);
globalPowerVersion.incrementAndGet();
int power = 0; int power = 0;
for (Iterator<IRedstoneLinkable> iterator = network.iterator(); iterator.hasNext();) { for (Iterator<IRedstoneLinkable> iterator = network.iterator(); iterator.hasNext();) {
@ -141,7 +144,7 @@ public class RedstoneLinkNetworkHandler {
.closerThan(to.getLocation(), AllConfigs.SERVER.logistics.linkRange.get()); .closerThan(to.getLocation(), AllConfigs.SERVER.logistics.linkRange.get());
} }
public Map<Pair<Frequency, Frequency>, Set<IRedstoneLinkable>> networksIn(LevelAccessor world) { public Map<Couple<Frequency>, Set<IRedstoneLinkable>> networksIn(LevelAccessor world) {
if (!connections.containsKey(world)) { if (!connections.containsKey(world)) {
Create.LOGGER.warn("Tried to Access unprepared network space of " + WorldHelper.getDimensionID(world)); Create.LOGGER.warn("Tried to Access unprepared network space of " + WorldHelper.getDimensionID(world));
return new HashMap<>(); return new HashMap<>();
@ -149,4 +152,16 @@ public class RedstoneLinkNetworkHandler {
return connections.get(world); return connections.get(world);
} }
public boolean hasAnyLoadedPower(Couple<Frequency> frequency) {
for (Map<Couple<Frequency>, Set<IRedstoneLinkable>> map : connections.values()) {
Set<IRedstoneLinkable> set = map.get(frequency);
if (set == null || set.isEmpty())
continue;
for (IRedstoneLinkable link : set)
if (link.getTransmittedStrength() > 0)
return true;
}
return false;
}
} }

View file

@ -1,10 +1,7 @@
package com.simibubi.create.content.logistics.block.display; package com.simibubi.create.content.logistics.block.display;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set;
import java.util.function.BiConsumer;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.jozufozu.flywheel.util.transform.TransformStack; import com.jozufozu.flywheel.util.transform.TransformStack;
@ -16,21 +13,18 @@ import com.simibubi.create.content.logistics.block.display.target.DisplayTargetS
import com.simibubi.create.foundation.gui.AbstractSimiScreen; import com.simibubi.create.foundation.gui.AbstractSimiScreen;
import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllGuiTextures;
import com.simibubi.create.foundation.gui.AllIcons; import com.simibubi.create.foundation.gui.AllIcons;
import com.simibubi.create.foundation.gui.UIRenderHelper; import com.simibubi.create.foundation.gui.ModularGuiLine;
import com.simibubi.create.foundation.gui.ModularGuiLineBuilder;
import com.simibubi.create.foundation.gui.element.GuiGameElement; import com.simibubi.create.foundation.gui.element.GuiGameElement;
import com.simibubi.create.foundation.gui.widget.IconButton; import com.simibubi.create.foundation.gui.widget.IconButton;
import com.simibubi.create.foundation.gui.widget.Label; import com.simibubi.create.foundation.gui.widget.Label;
import com.simibubi.create.foundation.gui.widget.ScrollInput; import com.simibubi.create.foundation.gui.widget.ScrollInput;
import com.simibubi.create.foundation.gui.widget.SelectionScrollInput; import com.simibubi.create.foundation.gui.widget.SelectionScrollInput;
import com.simibubi.create.foundation.gui.widget.TooltipArea;
import com.simibubi.create.foundation.networking.AllPackets; import com.simibubi.create.foundation.networking.AllPackets;
import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.Couple;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.Pair;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.client.gui.components.AbstractWidget;
import net.minecraft.client.gui.components.EditBox;
import net.minecraft.client.gui.components.events.GuiEventListener; import net.minecraft.client.gui.components.events.GuiEventListener;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
@ -63,13 +57,13 @@ public class DisplayLinkScreen extends AbstractSimiScreen {
ScrollInput targetLineSelector; ScrollInput targetLineSelector;
Label targetLineLabel; Label targetLineLabel;
Couple<Set<Pair<AbstractWidget, String>>> configWidgets; Couple<ModularGuiLine> configWidgets;
public DisplayLinkScreen(DisplayLinkTileEntity te) { public DisplayLinkScreen(DisplayLinkTileEntity te) {
this.background = AllGuiTextures.DATA_GATHERER; this.background = AllGuiTextures.DATA_GATHERER;
this.te = te; this.te = te;
sources = Collections.emptyList(); sources = Collections.emptyList();
configWidgets = Couple.create(HashSet::new); configWidgets = Couple.create(ModularGuiLine::new);
target = null; target = null;
} }
@ -124,7 +118,7 @@ public class DisplayLinkScreen extends AbstractSimiScreen {
removeWidget(sourceTypeSelector); removeWidget(sourceTypeSelector);
removeWidget(sourceTypeLabel); removeWidget(sourceTypeLabel);
configWidgets.forEach(s -> s.forEach(p -> removeWidget(p.getFirst()))); configWidgets.forEach(s -> s.forEach(this::removeWidget));
targetLineSelector = null; targetLineSelector = null;
sourceTypeSelector = null; sourceTypeSelector = null;
@ -178,100 +172,22 @@ public class DisplayLinkScreen extends AbstractSimiScreen {
private void initGathererSourceSubOptions(int i) { private void initGathererSourceSubOptions(int i) {
DisplaySource source = sources.get(i); DisplaySource source = sources.get(i);
source.populateData(new DisplayLinkContext(te.getLevel(), te)); source.populateData(new DisplayLinkContext(te.getLevel(), te));
if (targetLineSelector != null) if (targetLineSelector != null)
targetLineSelector targetLineSelector
.titled(source instanceof SingleLineDisplaySource ? Lang.translate("display_link.display_on") .titled(source instanceof SingleLineDisplaySource ? Lang.translate("display_link.display_on")
: Lang.translate("display_link.display_on_multiline")); : Lang.translate("display_link.display_on_multiline"));
configWidgets.forEach(s -> { configWidgets.forEach(s -> {
s.forEach(p -> removeWidget(p.getFirst())); s.forEach(this::removeWidget);
s.clear(); s.clear();
}); });
DisplayLinkContext context = new DisplayLinkContext(minecraft.level, te); DisplayLinkContext context = new DisplayLinkContext(minecraft.level, te);
configWidgets.forEachWithContext((s, first) -> source.initConfigurationWidgets(context, configWidgets.forEachWithContext((s, first) -> source.initConfigurationWidgets(context,
new LineBuilder(s, guiLeft + 60, guiTop + (first ? 51 : 72)), first)); new ModularGuiLineBuilder(font, s, guiLeft + 60, guiTop + (first ? 51 : 72)), first));
configWidgets
configWidgets.forEach(s -> s.forEach(p -> { .forEach(s -> s.loadValues(te.getSourceConfig(), this::addRenderableWidget, this::addRenderableOnly));
loadValue(te.getSourceConfig(), p);
if (p.getFirst() instanceof TooltipArea)
addRenderableOnly(p.getFirst());
else
addRenderableWidget(p.getFirst());
}));
}
public class LineBuilder {
private Set<Pair<AbstractWidget, String>> targetSet;
private int x;
private int y;
public LineBuilder(Set<Pair<AbstractWidget, String>> targetSet, int x, int y) {
this.targetSet = targetSet;
this.x = x;
this.y = y;
}
public LineBuilder addScrollInput(int x, int width, BiConsumer<ScrollInput, Label> inputTransform,
String dataKey) {
ScrollInput input = new ScrollInput(x + this.x, y - 4, width, 18);
addScrollInput(input, inputTransform, dataKey);
return this;
}
public LineBuilder addSelectionScrollInput(int x, int width,
BiConsumer<SelectionScrollInput, Label> inputTransform, String dataKey) {
SelectionScrollInput input = new SelectionScrollInput(x + this.x, y - 4, width, 18);
addScrollInput(input, inputTransform, dataKey);
return this;
}
private <T extends ScrollInput> void addScrollInput(T input, BiConsumer<T, Label> inputTransform,
String dataKey) {
Label label = new Label(input.x + 5, y, TextComponent.EMPTY);
label.withShadow();
inputTransform.accept(input, label);
input.writingTo(label);
targetSet.add(Pair.of(label, "Dummy"));
targetSet.add(Pair.of(input, dataKey));
}
public LineBuilder addTextInput(int x, int width, BiConsumer<EditBox, TooltipArea> inputTransform,
String dataKey) {
EditBox input = new EditBox(font, x + this.x + 5, y, width - 9, 8, TextComponent.EMPTY);
input.setBordered(false);
input.setTextColor(0xffffff);
input.changeFocus(false);
input.mouseClicked(0, 0, 0);
TooltipArea tooltipArea = new TooltipArea(this.x + x, y - 4, width, 18);
inputTransform.accept(input, tooltipArea);
targetSet.add(Pair.of(input, dataKey));
targetSet.add(Pair.of(tooltipArea, "Dummy"));
return this;
}
}
private void saveValue(CompoundTag data, Pair<AbstractWidget, String> widget) {
AbstractWidget w = widget.getFirst();
String key = widget.getSecond();
if (w instanceof EditBox eb)
data.putString(key, eb.getValue());
if (w instanceof ScrollInput si)
data.putInt(key, si.getState());
}
private void loadValue(CompoundTag data, Pair<AbstractWidget, String> widget) {
AbstractWidget w = widget.getFirst();
String key = widget.getSecond();
if (!data.contains(key))
return;
if (w instanceof EditBox eb)
eb.setValue(data.getString(key));
if (w instanceof ScrollInput si)
si.setState(data.getInt(key));
} }
@Override @Override
@ -282,7 +198,7 @@ public class DisplayLinkScreen extends AbstractSimiScreen {
if (!sources.isEmpty()) { if (!sources.isEmpty()) {
sourceData.putString("Id", sourceData.putString("Id",
sources.get(sourceTypeSelector == null ? 0 : sourceTypeSelector.getState()).id.toString()); sources.get(sourceTypeSelector == null ? 0 : sourceTypeSelector.getState()).id.toString());
configWidgets.forEach(s -> s.forEach(p -> saveValue(sourceData, p))); configWidgets.forEach(s -> s.saveValues(sourceData));
} }
AllPackets.channel.sendToServer(new DisplayLinkConfigurationPacket(te.getBlockPos(), sourceData, AllPackets.channel.sendToServer(new DisplayLinkConfigurationPacket(te.getBlockPos(), sourceData,
@ -310,12 +226,14 @@ public class DisplayLinkScreen extends AbstractSimiScreen {
minecraft.getItemRenderer() minecraft.getItemRenderer()
.renderGuiItem(targetIcon, x + 37, y + 105); .renderGuiItem(targetIcon, x + 37, y + 105);
configWidgets.forEachWithContext((s, first) -> s.forEach(p -> { ms.pushPose();
if (p.getSecond() ms.translate(0, guiTop + 48, 0);
.equals("Dummy")) configWidgets.getFirst()
return; .renderWidgetBG(guiLeft, ms);
renderWidgetBG(ms, p.getFirst(), first); ms.translate(0, 21, 0);
})); configWidgets.getSecond()
.renderWidgetBG(guiLeft, ms);
ms.popPose();
ms.pushPose(); ms.pushPose();
TransformStack.cast(ms) TransformStack.cast(ms)
@ -330,21 +248,6 @@ public class DisplayLinkScreen extends AbstractSimiScreen {
ms.popPose(); ms.popPose();
} }
protected void renderWidgetBG(PoseStack ms, AbstractWidget aw, boolean firstLine) {
int x = aw.x;
int width = aw.getWidth();
int y = guiTop + (firstLine ? 46 : 67);
if (aw instanceof EditBox) {
x -= 5;
width += 9;
}
UIRenderHelper.drawStretched(ms, x, y, width, 18, -100, AllGuiTextures.DATA_AREA);
AllGuiTextures.DATA_AREA_START.render(ms, x, y);
AllGuiTextures.DATA_AREA_END.render(ms, x + width - 2, y);
}
@Override @Override
protected void renderWindowForeground(PoseStack ms, int mouseX, int mouseY, float partialTicks) { protected void renderWindowForeground(PoseStack ms, int mouseX, int mouseY, float partialTicks) {
super.renderWindowForeground(ms, mouseX, mouseY, partialTicks); super.renderWindowForeground(ms, mouseX, mouseY, partialTicks);

View file

@ -6,12 +6,12 @@ import java.util.List;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.simibubi.create.content.logistics.block.display.DisplayBehaviour; import com.simibubi.create.content.logistics.block.display.DisplayBehaviour;
import com.simibubi.create.content.logistics.block.display.DisplayLinkContext; import com.simibubi.create.content.logistics.block.display.DisplayLinkContext;
import com.simibubi.create.content.logistics.block.display.DisplayLinkScreen.LineBuilder;
import com.simibubi.create.content.logistics.block.display.target.DisplayBoardTarget; import com.simibubi.create.content.logistics.block.display.target.DisplayBoardTarget;
import com.simibubi.create.content.logistics.block.display.target.DisplayTarget; import com.simibubi.create.content.logistics.block.display.target.DisplayTarget;
import com.simibubi.create.content.logistics.block.display.target.DisplayTargetStats; import com.simibubi.create.content.logistics.block.display.target.DisplayTargetStats;
import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayLayout; import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayLayout;
import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayTileEntity; import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayTileEntity;
import com.simibubi.create.foundation.gui.ModularGuiLineBuilder;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent; import net.minecraft.network.chat.MutableComponent;
@ -70,6 +70,6 @@ public abstract class DisplaySource extends DisplayBehaviour {
} }
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public void initConfigurationWidgets(DisplayLinkContext context, LineBuilder builder, boolean isFirstLine) {} public void initConfigurationWidgets(DisplayLinkContext context, ModularGuiLineBuilder builder, boolean isFirstLine) {}
} }

View file

@ -3,11 +3,11 @@ package com.simibubi.create.content.logistics.block.display.source;
import static com.simibubi.create.content.logistics.trains.management.display.FlapDisplaySection.WIDE_MONOSPACE; import static com.simibubi.create.content.logistics.trains.management.display.FlapDisplaySection.WIDE_MONOSPACE;
import com.simibubi.create.content.logistics.block.display.DisplayLinkContext; import com.simibubi.create.content.logistics.block.display.DisplayLinkContext;
import com.simibubi.create.content.logistics.block.display.DisplayLinkScreen.LineBuilder;
import com.simibubi.create.content.logistics.block.display.target.DisplayTargetStats; import com.simibubi.create.content.logistics.block.display.target.DisplayTargetStats;
import com.simibubi.create.content.logistics.block.redstone.StockpileSwitchTileEntity; import com.simibubi.create.content.logistics.block.redstone.StockpileSwitchTileEntity;
import com.simibubi.create.content.logistics.trains.management.display.FlapDisplaySection; import com.simibubi.create.content.logistics.trains.management.display.FlapDisplaySection;
import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayTileEntity; import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayTileEntity;
import com.simibubi.create.foundation.gui.ModularGuiLineBuilder;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
import net.minecraft.network.chat.MutableComponent; import net.minecraft.network.chat.MutableComponent;
@ -83,7 +83,7 @@ public class FillLevelDisplaySource extends NumericSingleLineDisplaySource {
@Override @Override
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public void initConfigurationWidgets(DisplayLinkContext context, LineBuilder builder, boolean isFirstLine) { public void initConfigurationWidgets(DisplayLinkContext context, ModularGuiLineBuilder builder, boolean isFirstLine) {
super.initConfigurationWidgets(context, builder, isFirstLine); super.initConfigurationWidgets(context, builder, isFirstLine);
if (isFirstLine) if (isFirstLine)
return; return;

View file

@ -3,9 +3,9 @@ package com.simibubi.create.content.logistics.block.display.source;
import com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation; import com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation;
import com.simibubi.create.content.logistics.block.display.DisplayLinkBlock; import com.simibubi.create.content.logistics.block.display.DisplayLinkBlock;
import com.simibubi.create.content.logistics.block.display.DisplayLinkContext; import com.simibubi.create.content.logistics.block.display.DisplayLinkContext;
import com.simibubi.create.content.logistics.block.display.DisplayLinkScreen.LineBuilder;
import com.simibubi.create.content.logistics.block.display.DisplayLinkTileEntity; import com.simibubi.create.content.logistics.block.display.DisplayLinkTileEntity;
import com.simibubi.create.content.logistics.block.display.target.DisplayTargetStats; import com.simibubi.create.content.logistics.block.display.target.DisplayTargetStats;
import com.simibubi.create.foundation.gui.ModularGuiLineBuilder;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
@ -101,7 +101,7 @@ public class ItemThoughputDisplaySource extends AccumulatedItemCountDisplaySourc
@Override @Override
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public void initConfigurationWidgets(DisplayLinkContext context, LineBuilder builder, boolean isFirstLine) { public void initConfigurationWidgets(DisplayLinkContext context, ModularGuiLineBuilder builder, boolean isFirstLine) {
super.initConfigurationWidgets(context, builder, isFirstLine); super.initConfigurationWidgets(context, builder, isFirstLine);
if (isFirstLine) if (isFirstLine)
return; return;

View file

@ -4,7 +4,7 @@ import java.util.stream.Stream;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.simibubi.create.content.logistics.block.display.DisplayLinkContext; import com.simibubi.create.content.logistics.block.display.DisplayLinkContext;
import com.simibubi.create.content.logistics.block.display.DisplayLinkScreen.LineBuilder; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder;
import com.simibubi.create.foundation.utility.IntAttached; import com.simibubi.create.foundation.utility.IntAttached;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
@ -56,7 +56,7 @@ public class ScoreboardDisplaySource extends ValueListDisplaySource {
} }
@Override @Override
public void initConfigurationWidgets(DisplayLinkContext context, LineBuilder builder, boolean isFirstLine) { public void initConfigurationWidgets(DisplayLinkContext context, ModularGuiLineBuilder builder, boolean isFirstLine) {
if (isFirstLine) if (isFirstLine)
builder.addTextInput(0, 137, (e, t) -> { builder.addTextInput(0, 137, (e, t) -> {
e.setValue(""); e.setValue("");

View file

@ -4,11 +4,11 @@ import java.util.List;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.simibubi.create.content.logistics.block.display.DisplayLinkContext; import com.simibubi.create.content.logistics.block.display.DisplayLinkContext;
import com.simibubi.create.content.logistics.block.display.DisplayLinkScreen.LineBuilder;
import com.simibubi.create.content.logistics.block.display.target.DisplayTargetStats; import com.simibubi.create.content.logistics.block.display.target.DisplayTargetStats;
import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayLayout; import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayLayout;
import com.simibubi.create.content.logistics.trains.management.display.FlapDisplaySection; import com.simibubi.create.content.logistics.trains.management.display.FlapDisplaySection;
import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayTileEntity; import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayTileEntity;
import com.simibubi.create.foundation.gui.ModularGuiLineBuilder;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
@ -25,13 +25,13 @@ public abstract class SingleLineDisplaySource extends DisplaySource {
@Override @Override
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public void initConfigurationWidgets(DisplayLinkContext context, LineBuilder builder, boolean isFirstLine) { public void initConfigurationWidgets(DisplayLinkContext context, ModularGuiLineBuilder builder, boolean isFirstLine) {
if (isFirstLine && allowsLabeling(context)) if (isFirstLine && allowsLabeling(context))
addLabelingTextBox(builder); addLabelingTextBox(builder);
} }
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
protected void addLabelingTextBox(LineBuilder builder) { protected void addLabelingTextBox(ModularGuiLineBuilder builder) {
builder.addTextInput(0, 137, (e, t) -> { builder.addTextInput(0, 137, (e, t) -> {
e.setValue(""); e.setValue("");
t.withTooltip(ImmutableList.of(Lang.translate("display_source.label") t.withTooltip(ImmutableList.of(Lang.translate("display_source.label")

View file

@ -3,7 +3,7 @@ package com.simibubi.create.content.logistics.block.display.source;
import java.util.stream.Stream; import java.util.stream.Stream;
import com.simibubi.create.content.logistics.block.display.DisplayLinkContext; import com.simibubi.create.content.logistics.block.display.DisplayLinkContext;
import com.simibubi.create.content.logistics.block.display.DisplayLinkScreen.LineBuilder; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder;
import com.simibubi.create.foundation.utility.IntAttached; import com.simibubi.create.foundation.utility.IntAttached;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
@ -58,6 +58,6 @@ public abstract class StatTrackingDisplaySource extends ScoreboardDisplaySource
@Override @Override
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public void initConfigurationWidgets(DisplayLinkContext context, LineBuilder builder, boolean isFirstLine) {} public void initConfigurationWidgets(DisplayLinkContext context, ModularGuiLineBuilder builder, boolean isFirstLine) {}
} }

View file

@ -7,7 +7,6 @@ import java.util.List;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.simibubi.create.content.logistics.block.display.DisplayLinkContext; import com.simibubi.create.content.logistics.block.display.DisplayLinkContext;
import com.simibubi.create.content.logistics.block.display.DisplayLinkScreen.LineBuilder;
import com.simibubi.create.content.logistics.block.display.target.DisplayTargetStats; import com.simibubi.create.content.logistics.block.display.target.DisplayTargetStats;
import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayLayout; import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayLayout;
import com.simibubi.create.content.logistics.trains.management.display.FlapDisplaySection; import com.simibubi.create.content.logistics.trains.management.display.FlapDisplaySection;
@ -15,6 +14,7 @@ import com.simibubi.create.content.logistics.trains.management.display.FlapDispl
import com.simibubi.create.content.logistics.trains.management.display.GlobalTrainDisplayData; import com.simibubi.create.content.logistics.trains.management.display.GlobalTrainDisplayData;
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.GlobalStation; import com.simibubi.create.content.logistics.trains.management.edgePoint.station.GlobalStation;
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.StationTileEntity; import com.simibubi.create.content.logistics.trains.management.edgePoint.station.StationTileEntity;
import com.simibubi.create.foundation.gui.ModularGuiLineBuilder;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
@ -171,7 +171,7 @@ public class StationSummaryDisplaySource extends DisplaySource {
@Override @Override
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public void initConfigurationWidgets(DisplayLinkContext context, LineBuilder builder, boolean isFirstLine) { public void initConfigurationWidgets(DisplayLinkContext context, ModularGuiLineBuilder builder, boolean isFirstLine) {
if (isFirstLine) { if (isFirstLine) {
builder.addTextInput(0, 137, (e, t) -> { builder.addTextInput(0, 137, (e, t) -> {
e.setValue(""); e.setValue("");

View file

@ -3,9 +3,9 @@ package com.simibubi.create.content.logistics.block.display.source;
import com.simibubi.create.Create; import com.simibubi.create.Create;
import com.simibubi.create.content.contraptions.components.clock.CuckooClockTileEntity; import com.simibubi.create.content.contraptions.components.clock.CuckooClockTileEntity;
import com.simibubi.create.content.logistics.block.display.DisplayLinkContext; import com.simibubi.create.content.logistics.block.display.DisplayLinkContext;
import com.simibubi.create.content.logistics.block.display.DisplayLinkScreen.LineBuilder;
import com.simibubi.create.content.logistics.block.display.target.DisplayTargetStats; import com.simibubi.create.content.logistics.block.display.target.DisplayTargetStats;
import com.simibubi.create.content.logistics.trains.management.display.FlapDisplaySection; import com.simibubi.create.content.logistics.trains.management.display.FlapDisplaySection;
import com.simibubi.create.foundation.gui.ModularGuiLineBuilder;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
import net.minecraft.network.chat.MutableComponent; import net.minecraft.network.chat.MutableComponent;
@ -72,7 +72,7 @@ public class TimeOfDayDisplaySource extends SingleLineDisplaySource {
@Override @Override
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public void initConfigurationWidgets(DisplayLinkContext context, LineBuilder builder, boolean isFirstLine) { public void initConfigurationWidgets(DisplayLinkContext context, ModularGuiLineBuilder builder, boolean isFirstLine) {
super.initConfigurationWidgets(context, builder, isFirstLine); super.initConfigurationWidgets(context, builder, isFirstLine);
if (isFirstLine) if (isFirstLine)
return; return;

View file

@ -10,11 +10,11 @@ import java.util.stream.Stream;
import org.apache.commons.lang3.mutable.MutableInt; import org.apache.commons.lang3.mutable.MutableInt;
import com.simibubi.create.content.logistics.block.display.DisplayLinkContext; import com.simibubi.create.content.logistics.block.display.DisplayLinkContext;
import com.simibubi.create.content.logistics.block.display.DisplayLinkScreen.LineBuilder;
import com.simibubi.create.content.logistics.block.display.target.DisplayTargetStats; import com.simibubi.create.content.logistics.block.display.target.DisplayTargetStats;
import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayLayout; import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayLayout;
import com.simibubi.create.content.logistics.trains.management.display.FlapDisplaySection; import com.simibubi.create.content.logistics.trains.management.display.FlapDisplaySection;
import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayTileEntity; import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayTileEntity;
import com.simibubi.create.foundation.gui.ModularGuiLineBuilder;
import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.Couple;
import com.simibubi.create.foundation.utility.IntAttached; import com.simibubi.create.foundation.utility.IntAttached;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
@ -154,13 +154,13 @@ public abstract class ValueListDisplaySource extends DisplaySource {
@Override @Override
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public void initConfigurationWidgets(DisplayLinkContext context, LineBuilder builder, boolean isFirstLine) { public void initConfigurationWidgets(DisplayLinkContext context, ModularGuiLineBuilder builder, boolean isFirstLine) {
if (isFirstLine) if (isFirstLine)
addFullNumberConfig(builder); addFullNumberConfig(builder);
} }
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
protected void addFullNumberConfig(LineBuilder builder) { protected void addFullNumberConfig(ModularGuiLineBuilder builder) {
builder.addSelectionScrollInput(0, 75, builder.addSelectionScrollInput(0, 75,
(si, l) -> si.forOptions(Lang.translatedOptions("display_source.value_list", "shortened", "full_number")) (si, l) -> si.forOptions(Lang.translatedOptions("display_source.value_list", "shortened", "full_number"))
.titled(Lang.translate("display_source.value_list.display")), .titled(Lang.translate("display_source.value_list.display")),

View file

@ -1,8 +1,5 @@
package com.simibubi.create.content.logistics.item; package com.simibubi.create.content.logistics.item;
import org.apache.commons.lang3.tuple.Pair;
import com.simibubi.create.content.logistics.RedstoneLinkNetworkHandler.Frequency;
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
import com.simibubi.create.foundation.tileEntity.behaviour.linked.LinkBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.linked.LinkBehaviour;
@ -46,18 +43,15 @@ public class LinkedControllerBindPacket extends LinkedControllerPacketBase {
if (linkBehaviour == null) if (linkBehaviour == null)
return; return;
Pair<Frequency, Frequency> pair = linkBehaviour.getNetworkKey(); linkBehaviour.getNetworkKey()
frequencyItems.setStackInSlot(button * 2, pair.getKey() .forEachWithContext((f, first) -> frequencyItems.setStackInSlot(button * 2 + (first ? 0 : 1), f.getStack()
.getStack() .copy()));
.copy());
frequencyItems.setStackInSlot(button * 2 + 1, pair.getValue()
.getStack()
.copy());
heldItem.getTag().put("Items", frequencyItems.serializeNBT()); heldItem.getTag()
.put("Items", frequencyItems.serializeNBT());
} }
@Override @Override
protected void handleLectern(ServerPlayer player, LecternControllerTileEntity lectern) { } protected void handleLectern(ServerPlayer player, LecternControllerTileEntity lectern) {}
} }

View file

@ -114,8 +114,8 @@ public class LinkedControllerServerHandler {
} }
@Override @Override
public Pair<Frequency, Frequency> getNetworkKey() { public Couple<Frequency> getNetworkKey() {
return Pair.of(getSecond().getFirst(), getSecond().getSecond()); return getSecond();
} }
} }

View file

@ -19,8 +19,8 @@ import javax.annotation.Nullable;
import org.apache.commons.lang3.mutable.MutableDouble; import org.apache.commons.lang3.mutable.MutableDouble;
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
import com.simibubi.create.content.contraptions.components.structureMovement.MountedStorageManager;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher;
import com.simibubi.create.content.contraptions.components.structureMovement.train.TrainCargoManager;
import com.simibubi.create.content.logistics.trains.DimensionPalette; import com.simibubi.create.content.logistics.trains.DimensionPalette;
import com.simibubi.create.content.logistics.trains.TrackGraph; import com.simibubi.create.content.logistics.trains.TrackGraph;
import com.simibubi.create.content.logistics.trains.TrackNodeLocation; import com.simibubi.create.content.logistics.trains.TrackNodeLocation;
@ -59,7 +59,7 @@ public class Carriage {
public int bogeySpacing; public int bogeySpacing;
public Couple<CarriageBogey> bogeys; public Couple<CarriageBogey> bogeys;
public MountedStorageManager storage; public TrainCargoManager storage;
CompoundTag serialisedEntity; CompoundTag serialisedEntity;
Map<Integer, CompoundTag> serialisedPassengers; Map<Integer, CompoundTag> serialisedPassengers;
@ -76,7 +76,7 @@ public class Carriage {
this.presentConductors = Couple.create(false, false); this.presentConductors = Couple.create(false, false);
this.serialisedPassengers = new HashMap<>(); this.serialisedPassengers = new HashMap<>();
this.entities = new HashMap<>(); this.entities = new HashMap<>();
this.storage = new MountedStorageManager(); this.storage = new TrainCargoManager();
bogey1.setLeading(); bogey1.setLeading();
bogey1.carriage = this; bogey1.carriage = this;
@ -775,7 +775,7 @@ public class Carriage {
cce.setGraph(train.graph == null ? null : train.graph.id); cce.setGraph(train.graph == null ? null : train.graph.id);
cce.setCarriage(Carriage.this); cce.setCarriage(Carriage.this);
cce.syncCarriage(); cce.syncCarriage();
if (level instanceof ServerLevel sl) if (level instanceof ServerLevel sl)
sl.addFreshEntity(entity); sl.addFreshEntity(entity);

View file

@ -11,6 +11,7 @@ import java.util.Optional;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException; import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType;
@ -18,6 +19,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.Mou
import com.simibubi.create.content.contraptions.components.structureMovement.NonStationaryLighter; import com.simibubi.create.content.contraptions.components.structureMovement.NonStationaryLighter;
import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.ControlsBlock; import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.ControlsBlock;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionLighter; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionLighter;
import com.simibubi.create.content.contraptions.components.structureMovement.train.TrainCargoManager;
import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock; import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock;
import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock.HeatLevel; import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock.HeatLevel;
import com.simibubi.create.content.logistics.trains.IBogeyBlock; import com.simibubi.create.content.logistics.trains.IBogeyBlock;
@ -42,6 +44,7 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemp
import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.AABB;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.items.IItemHandlerModifiable; import net.minecraftforge.items.IItemHandlerModifiable;
@ -74,6 +77,7 @@ public class CarriageContraption extends Contraption {
soundQueue = new ArrivalSoundQueue(); soundQueue = new ArrivalSoundQueue();
portalCutoffMin = Integer.MIN_VALUE; portalCutoffMin = Integer.MIN_VALUE;
portalCutoffMax = Integer.MAX_VALUE; portalCutoffMax = Integer.MAX_VALUE;
storage = new TrainCargoManager();
} }
public void setSoundQueueOffset(int offset) { public void setSoundQueueOffset(int offset) {
@ -127,12 +131,12 @@ public class CarriageContraption extends Contraption {
// carriage manages it instead // carriage manages it instead
Carriage carriage = cce.getCarriage(); Carriage carriage = cce.getCarriage();
if (carriage.storage == null) { if (carriage.storage == null) {
carriage.storage = storage; carriage.storage = (TrainCargoManager) storage;
storage = new MountedStorageManager(); storage = new MountedStorageManager();
} }
storageProxy = carriage.storage; storageProxy = carriage.storage;
} }
public void returnStorageForDisassembly(MountedStorageManager storage) { public void returnStorageForDisassembly(MountedStorageManager storage) {
this.storage = storage; this.storage = storage;
} }
@ -325,5 +329,16 @@ public class CarriageContraption extends Contraption {
return storageProxy.getFluids(); return storageProxy.getFluids();
} }
public void handleContraptionFluidPacket(BlockPos localPos, FluidStack containedFluid) {
storage.updateContainedFluid(localPos, containedFluid);
}
@Override
public void tickStorage(AbstractContraptionEntity entity) {
if (entity.level.isClientSide)
storage.entityTick(entity);
else if (storageProxy != null)
storageProxy.entityTick(entity);
}
} }

View file

@ -133,7 +133,7 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
} }
public boolean isLocalCoordWithin(BlockPos localPos, int min, int max) { public boolean isLocalCoordWithin(BlockPos localPos, int min, int max) {
if (!(getContraption()instanceof CarriageContraption cc)) if (!(getContraption() instanceof CarriageContraption cc))
return false; return false;
Direction facing = cc.getAssemblyDirection(); Direction facing = cc.getAssemblyDirection();
Axis axis = facing.getClockWise() Axis axis = facing.getClockWise()
@ -186,6 +186,8 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
dimensional.pivot = null; dimensional.pivot = null;
carriage.updateContraptionAnchors(); carriage.updateContraptionAnchors();
dimensional.updateRenderedCutoff(); dimensional.updateRenderedCutoff();
carriage.storage.bindTanks(contraption.presentTileEntities);
} }
updateTrackGraph(); updateTrackGraph();
} else } else
@ -497,7 +499,7 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
if (targetSpeed != 0) if (targetSpeed != 0)
carriage.train.burnFuel(); carriage.train.burnFuel();
boolean slow = inverted ^ targetSpeed < 0; boolean slow = inverted ^ targetSpeed < 0;
boolean spaceDown = heldControls.contains(4); boolean spaceDown = heldControls.contains(4);
GlobalStation currentStation = carriage.train.getCurrentStation(); GlobalStation currentStation = carriage.train.getCurrentStation();
@ -611,7 +613,7 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
this.carriageIndex = carriage.train.carriages.indexOf(carriage); this.carriageIndex = carriage.train.carriages.indexOf(carriage);
if (contraption instanceof CarriageContraption cc) if (contraption instanceof CarriageContraption cc)
cc.swapStorageAfterAssembly(this); cc.swapStorageAfterAssembly(this);
DimensionalCarriageEntity dimensional = carriage.getDimensional(level); DimensionalCarriageEntity dimensional = carriage.getDimensional(level);
dimensional.pivot = null; dimensional.pivot = null;
carriage.updateContraptionAnchors(); carriage.updateContraptionAnchors();

View file

@ -169,6 +169,9 @@ public class Train {
updateConductors(); updateConductors();
return; return;
} }
if (heldForAssembly && getCurrentStation() == null)
heldForAssembly = false;
updateConductors(); updateConductors();
runtime.tick(level); runtime.tick(level);
@ -290,7 +293,7 @@ public class Train {
public IEdgePointListener frontSignalListener() { public IEdgePointListener frontSignalListener() {
return (distance, couple) -> { return (distance, couple) -> {
if (couple.getFirst()instanceof GlobalStation station) { if (couple.getFirst() instanceof GlobalStation station) {
if (!station.canApproachFrom(couple.getSecond() if (!station.canApproachFrom(couple.getSecond()
.getSecond()) || navigation.destination != station) .getSecond()) || navigation.destination != station)
return false; return false;
@ -302,7 +305,7 @@ public class Train {
return true; return true;
} }
if (!(couple.getFirst()instanceof SignalBoundary signal)) if (!(couple.getFirst() instanceof SignalBoundary signal))
return false; return false;
if (navigation.waitingForSignal != null && navigation.waitingForSignal.getFirst() if (navigation.waitingForSignal != null && navigation.waitingForSignal.getFirst()
.equals(signal.id)) { .equals(signal.id)) {
@ -333,7 +336,7 @@ public class Train {
public IEdgePointListener backSignalListener() { public IEdgePointListener backSignalListener() {
return (distance, couple) -> { return (distance, couple) -> {
if (!(couple.getFirst()instanceof SignalBoundary signal)) if (!(couple.getFirst() instanceof SignalBoundary signal))
return false; return false;
UUID groupId = signal.getGroup(couple.getSecond() UUID groupId = signal.getGroup(couple.getSecond()
.getFirst()); .getFirst());
@ -547,7 +550,7 @@ public class Train {
if (entity == null) if (entity == null)
return false; return false;
if (entity.getContraption()instanceof CarriageContraption cc) if (entity.getContraption() instanceof CarriageContraption cc)
cc.returnStorageForDisassembly(carriage.storage); cc.returnStorageForDisassembly(carriage.storage);
entity.setPos(Vec3 entity.setPos(Vec3
.atLowerCornerOf(pos.relative(assemblyDirection, backwards ? offset + carriage.bogeySpacing : offset))); .atLowerCornerOf(pos.relative(assemblyDirection, backwards ? offset + carriage.bogeySpacing : offset)));
@ -813,7 +816,7 @@ public class Train {
forEachTravellingPointBackwards((tp, d) -> { forEachTravellingPointBackwards((tp, d) -> {
signalScout.travel(graph, d, signalScout.follow(tp), (distance, couple) -> { signalScout.travel(graph, d, signalScout.follow(tp), (distance, couple) -> {
if (!(couple.getFirst()instanceof SignalBoundary signal)) if (!(couple.getFirst() instanceof SignalBoundary signal))
return false; return false;
couple.getSecond() couple.getSecond()
.map(signal::getGroup) .map(signal::getGroup)

View file

@ -1,15 +1,15 @@
package com.simibubi.create.content.logistics.trains.management.schedule; package com.simibubi.create.content.logistics.trains.management.schedule;
import java.util.List; import java.util.List;
import java.util.function.BiConsumer;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.foundation.gui.ModularGuiLineBuilder;
import com.simibubi.create.foundation.utility.Pair; import com.simibubi.create.foundation.utility.Pair;
import net.minecraft.client.gui.components.events.GuiEventListener; import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent; import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
@ -23,31 +23,36 @@ public interface IScheduleInput {
public abstract ResourceLocation getId(); public abstract ResourceLocation getId();
public default boolean needsSlot() { public abstract CompoundTag getData();
return false;
}
@OnlyIn(Dist.CLIENT) public default int slotsTargeted() {
public default void createWidgets(ScheduleScreen screen, return 0;
List<Pair<GuiEventListener, BiConsumer<IScheduleInput, GuiEventListener>>> editorSubWidgets, }
List<Integer> dividers, int x, int y) {}
public default List<Component> getTitleAs(String type) { public default List<Component> getTitleAs(String type) {
ResourceLocation id = getId(); ResourceLocation id = getId();
return ImmutableList.of(new TranslatableComponent(id.getNamespace() + ".schedule." + type + "." + id.getPath())); return ImmutableList
.of(new TranslatableComponent(id.getNamespace() + ".schedule." + type + "." + id.getPath()));
} }
public default ItemStack getSecondLineIcon() { public default ItemStack getSecondLineIcon() {
return ItemStack.EMPTY; return ItemStack.EMPTY;
} }
public default void setItem(ItemStack stack) {} public default void setItem(int slot, ItemStack stack) {}
public default ItemStack getItem(int slot) {
return ItemStack.EMPTY;
}
@Nullable @Nullable
public default List<Component> getSecondLineTooltip() { public default List<Component> getSecondLineTooltip(int slot) {
return null; return null;
} }
@OnlyIn(Dist.CLIENT)
public default void initConfigurationWidgets(ModularGuiLineBuilder builder) {};
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public default boolean renderSpecialIcon(PoseStack ms, int x, int y) { public default boolean renderSpecialIcon(PoseStack ms, int x, int y) {
return false; return false;

View file

@ -8,6 +8,7 @@ import com.simibubi.create.Create;
import com.simibubi.create.content.logistics.trains.management.schedule.condition.FluidThresholdCondition; import com.simibubi.create.content.logistics.trains.management.schedule.condition.FluidThresholdCondition;
import com.simibubi.create.content.logistics.trains.management.schedule.condition.IdleCargoCondition; import com.simibubi.create.content.logistics.trains.management.schedule.condition.IdleCargoCondition;
import com.simibubi.create.content.logistics.trains.management.schedule.condition.ItemThresholdCondition; import com.simibubi.create.content.logistics.trains.management.schedule.condition.ItemThresholdCondition;
import com.simibubi.create.content.logistics.trains.management.schedule.condition.RedstoneLinkCondition;
import com.simibubi.create.content.logistics.trains.management.schedule.condition.ScheduleWaitCondition; import com.simibubi.create.content.logistics.trains.management.schedule.condition.ScheduleWaitCondition;
import com.simibubi.create.content.logistics.trains.management.schedule.condition.ScheduledDelay; import com.simibubi.create.content.logistics.trains.management.schedule.condition.ScheduledDelay;
import com.simibubi.create.content.logistics.trains.management.schedule.condition.StationPoweredCondition; import com.simibubi.create.content.logistics.trains.management.schedule.condition.StationPoweredCondition;
@ -40,6 +41,7 @@ public class Schedule {
registerCondition("time_of_day", TimeOfDayCondition::new); registerCondition("time_of_day", TimeOfDayCondition::new);
registerCondition("fluid_threshold", FluidThresholdCondition::new); registerCondition("fluid_threshold", FluidThresholdCondition::new);
registerCondition("item_threshold", ItemThresholdCondition::new); registerCondition("item_threshold", ItemThresholdCondition::new);
registerCondition("redstone_link", RedstoneLinkCondition::new);
registerCondition("idle", IdleCargoCondition::new); registerCondition("idle", IdleCargoCondition::new);
registerCondition("unloaded", StationUnloadedCondition::new); registerCondition("unloaded", StationUnloadedCondition::new);
registerCondition("powered", StationPoweredCondition::new); registerCondition("powered", StationPoweredCondition::new);

View file

@ -17,8 +17,10 @@ import net.minecraftforge.items.SlotItemHandler;
public class ScheduleContainer extends GhostItemContainer<ItemStack> { public class ScheduleContainer extends GhostItemContainer<ItemStack> {
public boolean slotsActive = true; public boolean slotsActive = true;
public boolean targetSlotActive = true; public int targetSlotsActive = 1;
static final int slots = 2;
public ScheduleContainer(MenuType<?> type, int id, Inventory inv, FriendlyByteBuf extraData) { public ScheduleContainer(MenuType<?> type, int id, Inventory inv, FriendlyByteBuf extraData) {
super(type, id, inv, extraData); super(type, id, inv, extraData);
} }
@ -29,7 +31,7 @@ public class ScheduleContainer extends GhostItemContainer<ItemStack> {
@Override @Override
protected ItemStackHandler createGhostInventory() { protected ItemStackHandler createGhostInventory() {
return new ItemStackHandler(1); return new ItemStackHandler(slots);
} }
@Override @Override
@ -51,9 +53,10 @@ public class ScheduleContainer extends GhostItemContainer<ItemStack> {
@Override @Override
protected void addSlots() { protected void addSlots() {
addPlayerSlots(46, 140); addPlayerSlots(46, 140);
addSlot(new InactiveItemHandlerSlot(ghostInventory, 0, 54, 88)); for (int i = 0; i < slots; i++)
addSlot(new InactiveItemHandlerSlot(ghostInventory, i, i, 54 + 20 * i, 88));
} }
@Override @Override
protected void addPlayerSlots(int x, int y) { protected void addPlayerSlots(int x, int y) {
for (int hotbarSlot = 0; hotbarSlot < 9; ++hotbarSlot) for (int hotbarSlot = 0; hotbarSlot < 9; ++hotbarSlot)
@ -70,31 +73,35 @@ public class ScheduleContainer extends GhostItemContainer<ItemStack> {
public boolean stillValid(Player player) { public boolean stillValid(Player player) {
return playerInventory.getSelected() == contentHolder; return playerInventory.getSelected() == contentHolder;
} }
class InactiveSlot extends Slot { class InactiveSlot extends Slot {
public InactiveSlot(Container pContainer, int pIndex, int pX, int pY) { public InactiveSlot(Container pContainer, int pIndex, int pX, int pY) {
super(pContainer, pIndex, pX, pY); super(pContainer, pIndex, pX, pY);
} }
@Override @Override
public boolean isActive() { public boolean isActive() {
return slotsActive; return slotsActive;
} }
} }
class InactiveItemHandlerSlot extends SlotItemHandler { class InactiveItemHandlerSlot extends SlotItemHandler {
public InactiveItemHandlerSlot(IItemHandler itemHandler, int index, int xPosition, int yPosition) { private int targetIndex;
public InactiveItemHandlerSlot(IItemHandler itemHandler, int targetIndex, int index, int xPosition,
int yPosition) {
super(itemHandler, index, xPosition, yPosition); super(itemHandler, index, xPosition, yPosition);
this.targetIndex = targetIndex;
} }
@Override @Override
public boolean isActive() { public boolean isActive() {
return slotsActive && targetSlotActive; return slotsActive && targetIndex < targetSlotsActive;
} }
} }
} }

View file

@ -0,0 +1,35 @@
package com.simibubi.create.content.logistics.trains.management.schedule;
import net.minecraft.nbt.CompoundTag;
public abstract class ScheduleDataEntry implements IScheduleInput {
protected CompoundTag data;
public ScheduleDataEntry() {
data = new CompoundTag();
}
@Override
public CompoundTag getData() {
return data;
}
protected void writeAdditional(CompoundTag tag) {};
protected void readAdditional(CompoundTag tag) {};
protected <T> T enumData(String key, Class<T> enumClass) {
T[] enumConstants = enumClass.getEnumConstants();
return enumConstants[data.getInt(key) % enumConstants.length];
}
protected String textData(String key) {
return data.getString(key);
}
protected int intData(String key) {
return data.getInt(key);
}
}

View file

@ -6,12 +6,13 @@ import java.util.List;
import java.util.Objects; import java.util.Objects;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
import com.simibubi.create.content.logistics.trains.entity.Carriage;
import com.simibubi.create.content.logistics.trains.entity.Train; import com.simibubi.create.content.logistics.trains.entity.Train;
import com.simibubi.create.content.logistics.trains.management.display.GlobalTrainDisplayData.TrainDeparturePrediction; import com.simibubi.create.content.logistics.trains.management.display.GlobalTrainDisplayData.TrainDeparturePrediction;
import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType; import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType;
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.GlobalStation; import com.simibubi.create.content.logistics.trains.management.edgePoint.station.GlobalStation;
import com.simibubi.create.content.logistics.trains.management.schedule.condition.ScheduleWaitCondition; import com.simibubi.create.content.logistics.trains.management.schedule.condition.ScheduleWaitCondition;
import com.simibubi.create.content.logistics.trains.management.schedule.condition.TimedWaitCondition; import com.simibubi.create.content.logistics.trains.management.schedule.condition.ScheduledDelay;
import com.simibubi.create.content.logistics.trains.management.schedule.destination.ChangeTitleInstruction; import com.simibubi.create.content.logistics.trains.management.schedule.destination.ChangeTitleInstruction;
import com.simibubi.create.content.logistics.trains.management.schedule.destination.DestinationInstruction; import com.simibubi.create.content.logistics.trains.management.schedule.destination.DestinationInstruction;
import com.simibubi.create.content.logistics.trains.management.schedule.destination.ScheduleInstruction; import com.simibubi.create.content.logistics.trains.management.schedule.destination.ScheduleInstruction;
@ -57,6 +58,8 @@ public class ScheduleRuntime {
return; return;
state = State.POST_TRANSIT; state = State.POST_TRANSIT;
conditionProgress.clear(); conditionProgress.clear();
for (Carriage carriage : train.carriages)
carriage.storage.resetIdleCargoTracker();
if (ticksInTransit > 0) { if (ticksInTransit > 0) {
int current = predictionTicks.get(currentEntry); int current = predictionTicks.get(currentEntry);
@ -143,6 +146,9 @@ public class ScheduleRuntime {
conditionProgress.set(i, progress + 1); conditionProgress.set(i, progress + 1);
} }
} }
for (Carriage carriage : train.carriages)
carriage.storage.tickIdleCargoTracker();
} }
public GlobalStation startCurrentInstruction() { public GlobalStation startCurrentInstruction() {
@ -322,8 +328,8 @@ public class ScheduleRuntime {
ScheduleEntry scheduleEntry = schedule.entries.get(index); ScheduleEntry scheduleEntry = schedule.entries.get(index);
for (List<ScheduleWaitCondition> list : scheduleEntry.conditions) for (List<ScheduleWaitCondition> list : scheduleEntry.conditions)
for (ScheduleWaitCondition condition : list) for (ScheduleWaitCondition condition : list)
if (condition instanceof TimedWaitCondition wait) if (condition instanceof ScheduledDelay wait)
return wait.timeUnit.ticksPer * wait.value; return wait.totalWaitTicks();
return 5; // TODO properly ask conditions for time prediction return 5; // TODO properly ask conditions for time prediction
} }

View file

@ -7,7 +7,6 @@ import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.Consumer; import java.util.function.Consumer;
import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL11;
@ -26,15 +25,16 @@ import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePoi
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.GlobalStation; import com.simibubi.create.content.logistics.trains.management.edgePoint.station.GlobalStation;
import com.simibubi.create.content.logistics.trains.management.schedule.condition.ScheduleWaitCondition; import com.simibubi.create.content.logistics.trains.management.schedule.condition.ScheduleWaitCondition;
import com.simibubi.create.content.logistics.trains.management.schedule.condition.ScheduledDelay; import com.simibubi.create.content.logistics.trains.management.schedule.condition.ScheduledDelay;
import com.simibubi.create.content.logistics.trains.management.schedule.condition.TimedWaitCondition.TimeUnit;
import com.simibubi.create.content.logistics.trains.management.schedule.destination.DestinationInstruction; import com.simibubi.create.content.logistics.trains.management.schedule.destination.DestinationInstruction;
import com.simibubi.create.content.logistics.trains.management.schedule.destination.ScheduleInstruction; import com.simibubi.create.content.logistics.trains.management.schedule.destination.ScheduleInstruction;
import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllGuiTextures;
import com.simibubi.create.foundation.gui.AllIcons; import com.simibubi.create.foundation.gui.AllIcons;
import com.simibubi.create.foundation.gui.ModularGuiLine;
import com.simibubi.create.foundation.gui.ModularGuiLineBuilder;
import com.simibubi.create.foundation.gui.UIRenderHelper; import com.simibubi.create.foundation.gui.UIRenderHelper;
import com.simibubi.create.foundation.gui.container.AbstractSimiContainerScreen; import com.simibubi.create.foundation.gui.container.AbstractSimiContainerScreen;
import com.simibubi.create.foundation.gui.container.GhostItemSubmitPacket;
import com.simibubi.create.foundation.gui.element.GuiGameElement; import com.simibubi.create.foundation.gui.element.GuiGameElement;
import com.simibubi.create.foundation.gui.widget.AbstractSimiWidget;
import com.simibubi.create.foundation.gui.widget.IconButton; import com.simibubi.create.foundation.gui.widget.IconButton;
import com.simibubi.create.foundation.gui.widget.Indicator; import com.simibubi.create.foundation.gui.widget.Indicator;
import com.simibubi.create.foundation.gui.widget.Indicator.State; import com.simibubi.create.foundation.gui.widget.Indicator.State;
@ -52,7 +52,6 @@ import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Font; import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.components.EditBox; import net.minecraft.client.gui.components.EditBox;
import net.minecraft.client.gui.components.Widget; import net.minecraft.client.gui.components.Widget;
import net.minecraft.client.gui.components.events.GuiEventListener;
import net.minecraft.client.renderer.Rect2i; import net.minecraft.client.renderer.Rect2i;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
@ -90,9 +89,8 @@ public class ScheduleScreen extends AbstractSimiContainerScreen<ScheduleContaine
private SelectionScrollInput scrollInput; private SelectionScrollInput scrollInput;
private Label scrollInputLabel; private Label scrollInputLabel;
private IconButton editorConfirm, editorDelete; private IconButton editorConfirm, editorDelete;
private ModularGuiLine editorSubWidgets;
private Consumer<Boolean> onEditorClose; private Consumer<Boolean> onEditorClose;
private List<Pair<GuiEventListener, BiConsumer<IScheduleInput, GuiEventListener>>> editorSubWidgets;
private List<Integer> editorDividers;
private DestinationSuggestions destinationSuggestions; private DestinationSuggestions destinationSuggestions;
@ -104,7 +102,7 @@ public class ScheduleScreen extends AbstractSimiContainerScreen<ScheduleContaine
if (!tag.isEmpty()) if (!tag.isEmpty())
schedule = Schedule.fromTag(tag); schedule = Schedule.fromTag(tag);
container.slotsActive = false; container.slotsActive = false;
editorSubWidgets = new ArrayList<>(); editorSubWidgets = new ModularGuiLine();
} }
@Override @Override
@ -178,7 +176,13 @@ public class ScheduleScreen extends AbstractSimiContainerScreen<ScheduleContaine
if (allowDeletion) if (allowDeletion)
editorDelete = new IconButton(leftPos + 56 - 45, topPos + 65 + 22, AllIcons.I_TRASH); editorDelete = new IconButton(leftPos + 56 - 45, topPos + 65 + 22, AllIcons.I_TRASH);
menu.slotsActive = true; menu.slotsActive = true;
menu.targetSlotActive = field.needsSlot(); menu.targetSlotsActive = field.slotsTargeted();
for (int i = 0; i < field.slotsTargeted(); i++) {
ItemStack item = field.getItem(i);
menu.ghostInventory.setStackInSlot(i, item);
AllPackets.channel.sendToServer(new GhostItemSubmitPacket(item, i));
}
if (field instanceof ScheduleInstruction instruction) { if (field instanceof ScheduleInstruction instruction) {
int startIndex = 0; int startIndex = 0;
@ -260,15 +264,15 @@ public class ScheduleScreen extends AbstractSimiContainerScreen<ScheduleContaine
removeWidget(editorDelete); removeWidget(editorDelete);
IScheduleInput editing = editingCondition == null ? editingDestination : editingCondition; IScheduleInput editing = editingCondition == null ? editingDestination : editingCondition;
editing.setItem(menu.getSlot(36) for (int i = 0; i < editing.slotsTargeted(); i++) {
.getItem()); editing.setItem(i, menu.ghostInventory.getStackInSlot(i));
AllPackets.channel.sendToServer(new GhostItemSubmitPacket(ItemStack.EMPTY, i));
}
editorSubWidgets.forEach(p -> p.getSecond() editorSubWidgets.saveValues(editing.getData());
.accept(editing, p.getFirst())); editorSubWidgets.forEach(this::removeWidget);
editorSubWidgets.forEach(p -> removeWidget(p.getFirst()));
editorSubWidgets.clear(); editorSubWidgets.clear();
editorDividers = null;
editingCondition = null; editingCondition = null;
editingDestination = null; editingDestination = null;
editorConfirm = null; editorConfirm = null;
@ -279,32 +283,25 @@ public class ScheduleScreen extends AbstractSimiContainerScreen<ScheduleContaine
protected void updateEditorSubwidgets(IScheduleInput field) { protected void updateEditorSubwidgets(IScheduleInput field) {
destinationSuggestions = null; destinationSuggestions = null;
menu.targetSlotActive = field.needsSlot(); menu.targetSlotsActive = field.slotsTargeted();
editorSubWidgets.forEach(p -> removeWidget(p.getFirst()));
editorSubWidgets.forEach(this::removeWidget);
editorSubWidgets.clear(); editorSubWidgets.clear();
editorDividers = new ArrayList<>(); field.initConfigurationWidgets(
new ModularGuiLineBuilder(font, editorSubWidgets, getGuiLeft() + 77, getGuiTop() + 92).speechBubble());
editorSubWidgets.loadValues(field.getData(), this::addRenderableWidget, this::addRenderableOnly);
field.createWidgets(this, editorSubWidgets, editorDividers, leftPos - 2, topPos + 40); if (!(field instanceof DestinationInstruction))
return;
if (editorSubWidgets.isEmpty()) editorSubWidgets.forEach(e -> {
editorDividers = null; if (!(e instanceof EditBox destinationBox))
return;
if (field instanceof DestinationInstruction) {
EditBox destinationBox = (EditBox) editorSubWidgets.get(0)
.getFirst();
destinationSuggestions = new DestinationSuggestions(this.minecraft, this, destinationBox, this.font, destinationSuggestions = new DestinationSuggestions(this.minecraft, this, destinationBox, this.font,
getViableStations(field), topPos + 33); getViableStations(field), topPos + 33);
destinationSuggestions.setAllowSuggestions(true); destinationSuggestions.setAllowSuggestions(true);
destinationSuggestions.updateCommandInfo(); destinationSuggestions.updateCommandInfo();
destinationBox.setResponder(this::onDestinationEdited); destinationBox.setResponder(this::onDestinationEdited);
}
editorSubWidgets.forEach(pair -> {
GuiEventListener e = pair.getFirst();
if (e instanceof AbstractSimiWidget)
addRenderableWidget((AbstractSimiWidget) e);
if (e instanceof EditBox)
addRenderableWidget((EditBox) e);
}); });
} }
@ -839,8 +836,6 @@ public class ScheduleScreen extends AbstractSimiContainerScreen<ScheduleContaine
ArrayList<ScheduleWaitCondition> initialConditions = new ArrayList<>(); ArrayList<ScheduleWaitCondition> initialConditions = new ArrayList<>();
initialConditions.add(delay); initialConditions.add(delay);
entry.instruction = editingDestination; entry.instruction = editingDestination;
delay.value = 5;
delay.timeUnit = TimeUnit.SECONDS;
entry.conditions.add(initialConditions); entry.conditions.add(initialConditions);
schedule.entries.add(entry); schedule.entries.add(entry);
}, true); }, true);
@ -1005,16 +1000,21 @@ public class ScheduleScreen extends AbstractSimiContainerScreen<ScheduleContaine
if (editingCondition == null && editingDestination == null) if (editingCondition == null && editingDestination == null)
return; return;
int x = leftPos + 53; int x = leftPos + 53;
int y = topPos + 87; int y = topPos + 87;
if (mouseX < x || mouseY < y || mouseX >= x + 18 || mouseY >= y + 18) if (mouseX < x || mouseY < y || mouseX >= x + 120 || mouseY >= y + 18)
return; return;
IScheduleInput rendered = editingCondition == null ? editingDestination : editingCondition; IScheduleInput rendered = editingCondition == null ? editingDestination : editingCondition;
List<Component> secondLineTooltip = rendered.getSecondLineTooltip();
if (secondLineTooltip == null || (hoveredSlot != null && !hoveredSlot.getItem() for (int i = 0; i < Math.max(1, rendered.slotsTargeted()); i++) {
.isEmpty())) List<Component> secondLineTooltip = rendered.getSecondLineTooltip(i);
return; if (secondLineTooltip == null || (hoveredSlot != menu.getSlot(36 + i) || !hoveredSlot.getItem()
renderTooltip(matrixStack, secondLineTooltip, Optional.empty(), mouseX, mouseY); .isEmpty()))
continue;
renderTooltip(matrixStack, secondLineTooltip, Optional.empty(), mouseX, mouseY);
}
} }
@Override @Override
@ -1042,7 +1042,11 @@ public class ScheduleScreen extends AbstractSimiContainerScreen<ScheduleContaine
(float) topPos + 44, 0x505050); (float) topPos + 44, 0x505050);
IScheduleInput rendered = editingCondition == null ? editingDestination : editingCondition; IScheduleInput rendered = editingCondition == null ? editingDestination : editingCondition;
if (!rendered.needsSlot() && !rendered.renderSpecialIcon(pPoseStack, leftPos + 54, topPos + 88)) {
for (int i = 0; i < rendered.slotsTargeted(); i++)
AllGuiTextures.SCHEDULE_EDITOR_ADDITIONAL_SLOT.render(pPoseStack, leftPos + 53 + 20 * i, topPos + 87);
if (rendered.slotsTargeted() == 0 && !rendered.renderSpecialIcon(pPoseStack, leftPos + 54, topPos + 88)) {
Pair<ItemStack, Component> summary = rendered.getSummary(); Pair<ItemStack, Component> summary = rendered.getSummary();
ItemStack icon = summary.getFirst(); ItemStack icon = summary.getFirst();
if (icon.isEmpty()) if (icon.isEmpty())
@ -1055,12 +1059,10 @@ public class ScheduleScreen extends AbstractSimiContainerScreen<ScheduleContaine
.render(pPoseStack); .render(pPoseStack);
} }
if (editorDividers == null) pPoseStack.pushPose();
return; pPoseStack.translate(0, getGuiTop() + 87, 0);
editorSubWidgets.renderWidgetBG(getGuiLeft() + 77, pPoseStack);
AllGuiTextures.SCHEDULE_EDITOR_SECOND_LINE.render(pPoseStack, leftPos + 74, topPos + 87); pPoseStack.popPose();
for (Integer integer : editorDividers)
AllGuiTextures.SCHEDULE_EDITOR_DIVIDER.render(pPoseStack, leftPos + 74 + integer, topPos + 87);
} }
@Override @Override

View file

@ -2,29 +2,25 @@ package com.simibubi.create.content.logistics.trains.management.schedule.conditi
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.function.BiConsumer;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.simibubi.create.content.logistics.trains.management.schedule.IScheduleInput; import com.simibubi.create.Create;
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleScreen; import com.simibubi.create.content.logistics.trains.entity.Carriage;
import com.simibubi.create.foundation.gui.widget.Label; import com.simibubi.create.content.logistics.trains.entity.Train;
import com.simibubi.create.foundation.gui.widget.ScrollInput; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder;
import com.simibubi.create.foundation.gui.widget.SelectionScrollInput;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.NBTHelper;
import com.simibubi.create.foundation.utility.Pair; import com.simibubi.create.foundation.utility.Pair;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.client.gui.components.EditBox;
import net.minecraft.client.gui.components.events.GuiEventListener;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent; import net.minecraft.network.chat.TextComponent;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
public abstract class CargoThresholdCondition extends ScheduleWaitCondition { public abstract class CargoThresholdCondition extends LazyTickedScheduleCondition {
public static enum Ops { public static enum Ops {
GREATER(">"), LESS("<"), EQUAL("="); GREATER(">"), LESS("<"), EQUAL("=");
@ -34,6 +30,15 @@ public abstract class CargoThresholdCondition extends ScheduleWaitCondition {
this.formatted = formatted; this.formatted = formatted;
} }
public boolean test(int current, int target) {
return switch (this) {
case GREATER -> current > target;
case EQUAL -> current == target;
case LESS -> current < target;
default -> throw new IllegalArgumentException("Unexpected value: " + this);
};
}
public static List<? extends Component> translatedOptions() { public static List<? extends Component> translatedOptions() {
return Arrays.stream(values()) return Arrays.stream(values())
.map(op -> Lang.translate("schedule.condition.threshold." + Lang.asId(op.name()))) .map(op -> Lang.translate("schedule.condition.threshold." + Lang.asId(op.name())))
@ -41,8 +46,24 @@ public abstract class CargoThresholdCondition extends ScheduleWaitCondition {
} }
} }
public CargoThresholdCondition.Ops ops = Ops.GREATER; public CargoThresholdCondition() {
public int threshold; super(20);
data.putString("Threshold", "10");
}
@Override
public boolean lazyTickCompletion(Level level, Train train, CompoundTag context) {
int lastChecked = context.contains("LastChecked") ? context.getInt("LastChecked") : -1;
int status = 0;
for (Carriage carriage : train.carriages)
status += carriage.storage.getVersion();
if (status == lastChecked)
return false;
context.putInt("LastChecked", status);
return test(level, train);
}
protected abstract boolean test(Level level, Train train);
protected abstract Component getUnit(); protected abstract Component getUnit();
@ -50,28 +71,33 @@ public abstract class CargoThresholdCondition extends ScheduleWaitCondition {
@Override @Override
public Pair<ItemStack, Component> getSummary() { public Pair<ItemStack, Component> getSummary() {
return Pair.of(getIcon(), new TextComponent(ops.formatted + " " + threshold).append(getUnit())); return Pair.of(getIcon(), new TextComponent(getOperator().formatted + " " + getThreshold()).append(getUnit()));
} }
@Override @Override
protected void write(CompoundTag tag) { public int slotsTargeted() {
NBTHelper.writeEnum(tag, "Operator", ops); return 1;
tag.putInt("Threshold", threshold); }
public Ops getOperator() {
return enumData("Operator", Ops.class);
}
public int getThreshold() {
try {
return Integer.valueOf(textData("Threshold"));
} catch (NumberFormatException e) {
data.putString("Threshold", "0");
}
return 0;
}
public int getMeasure() {
return intData("Measure");
} }
@Override @Override
protected void read(CompoundTag tag) { public List<Component> getSecondLineTooltip(int slot) {
ops = NBTHelper.readEnum(tag, "Operator", CargoThresholdCondition.Ops.class);
threshold = tag.getInt("Threshold");
}
@Override
public boolean needsSlot() {
return true;
}
@Override
public List<Component> getSecondLineTooltip() {
return ImmutableList.of(Lang.translate("schedule.condition.threshold.place_item"), return ImmutableList.of(Lang.translate("schedule.condition.threshold.place_item"),
Lang.translate("schedule.condition.threshold.place_item_2") Lang.translate("schedule.condition.threshold.place_item_2")
.withStyle(ChatFormatting.GRAY)); .withStyle(ChatFormatting.GRAY));
@ -79,53 +105,14 @@ public abstract class CargoThresholdCondition extends ScheduleWaitCondition {
@Override @Override
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public void createWidgets(ScheduleScreen screen, public void initConfigurationWidgets(ModularGuiLineBuilder builder) {
List<Pair<GuiEventListener, BiConsumer<IScheduleInput, GuiEventListener>>> editorSubWidgets, builder.addSelectionScrollInput(0, 24, (i, l) -> {
List<Integer> dividers, int x, int y) { i.forOptions(Ops.translatedOptions())
super.createWidgets(screen, editorSubWidgets, dividers, x, y); .titled(Lang.translate("schedule.condition.threshold.train_holds"))
.format(state -> new TextComponent(" " + Ops.values()[state].formatted));
EditBox editBox = new EditBox(screen.getFont(), x + 109, y + 52, 35, 10, new TextComponent(threshold + "")); }, "Operator");
editBox.setBordered(false); builder.addIntegerTextInput(29, 41, (e, t) -> {
editBox.setValue(threshold + ""); }, "Threshold");
editBox.setTextColor(0xFFFFFF);
editBox.changeFocus(false);
editBox.mouseClicked(0, 0, 0);
editBox.setFilter(s -> {
if (s.isEmpty())
return true;
try {
Integer.parseInt(s);
return true;
} catch (NumberFormatException e) {
return false;
}
});
Label label = new Label(x + 87, y + 52, new TextComponent(ops.formatted)).withShadow();
label.text = new TextComponent(ops.formatted);
ScrollInput scrollInput = new SelectionScrollInput(x + 76, y + 48, 24, 16).forOptions(Ops.translatedOptions())
.titled(Lang.translate("schedule.condition.threshold.train_holds"))
.calling(state -> {
label.text = new TextComponent(Ops.values()[state].formatted);
})
.setState(ops.ordinal());
editorSubWidgets.add(Pair.of(editBox, (dest, box) -> {
CargoThresholdCondition c = (CargoThresholdCondition) dest;
String text = ((EditBox) box).getValue();
if (text.isEmpty())
c.threshold = 0;
else
c.threshold = Integer.parseInt(text);
}));
editorSubWidgets.add(Pair.of(scrollInput, (dest, box) -> {
CargoThresholdCondition c = (CargoThresholdCondition) dest;
c.ops = Ops.values()[((ScrollInput) box).getState()];
}));
editorSubWidgets.add(Pair.of(label, (d, l) -> {
}));
dividers.add(24);
dividers.add(70);
} }
} }

View file

@ -1,30 +1,28 @@
package com.simibubi.create.content.logistics.trains.management.schedule.condition; package com.simibubi.create.content.logistics.trains.management.schedule.condition;
import java.util.List; import java.util.List;
import java.util.function.BiConsumer;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.simibubi.create.Create; import com.simibubi.create.Create;
import com.simibubi.create.content.contraptions.processing.EmptyingByBasin; import com.simibubi.create.content.contraptions.processing.EmptyingByBasin;
import com.simibubi.create.content.logistics.item.filter.FilterItem; import com.simibubi.create.content.logistics.item.filter.FilterItem;
import com.simibubi.create.content.logistics.trains.management.schedule.IScheduleInput; import com.simibubi.create.content.logistics.trains.entity.Carriage;
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleScreen; import com.simibubi.create.content.logistics.trains.entity.Train;
import com.simibubi.create.foundation.gui.widget.Label; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.Pair;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.components.events.GuiEventListener;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent; import net.minecraft.network.chat.TextComponent;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.IFluidHandler;
public class FluidThresholdCondition extends CargoThresholdCondition { public class FluidThresholdCondition extends CargoThresholdCondition {
public ItemStack compareStack = ItemStack.EMPTY; public ItemStack compareStack = ItemStack.EMPTY;
@ -41,17 +39,46 @@ public class FluidThresholdCondition extends CargoThresholdCondition {
} }
@Override @Override
protected void write(CompoundTag tag) { protected boolean test(Level level, Train train) {
super.write(tag); Ops operator = getOperator();
int target = getThreshold();
if (compareStack.isEmpty())
return true;
int foundFluid = 0;
for (Carriage carriage : train.carriages) {
IFluidHandler fluids = carriage.storage.getFluids();
for (int i = 0; i < fluids.getTanks(); i++) {
FluidStack fluidInTank = fluids.getFluidInTank(i);
if (!FilterItem.test(level, fluidInTank, compareStack))
continue;
foundFluid += fluidInTank.getAmount();
if (operator != Ops.GREATER && foundFluid > target)
return false;
}
}
return operator.test(foundFluid, target * 1000);
}
@Override
protected void writeAdditional(CompoundTag tag) {
super.writeAdditional(tag);
tag.put("Bucket", compareStack.serializeNBT()); tag.put("Bucket", compareStack.serializeNBT());
} }
@Override @Override
protected void read(CompoundTag tag) { protected void readAdditional(CompoundTag tag) {
super.read(tag); super.readAdditional(tag);
compareStack = ItemStack.of(tag.getCompound("Bucket")); compareStack = ItemStack.of(tag.getCompound("Bucket"));
} }
@Override
public boolean tickCompletion(Level level, Train train, CompoundTag context) {
return super.tickCompletion(level, train, context);
}
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
private FluidStack loadFluid() { private FluidStack loadFluid() {
if (fluidStack != null) if (fluidStack != null)
@ -70,8 +97,8 @@ public class FluidThresholdCondition extends CargoThresholdCondition {
public List<Component> getTitleAs(String type) { public List<Component> getTitleAs(String type) {
return ImmutableList.of( return ImmutableList.of(
Lang.translate("schedule.condition.threshold.train_holds", Lang.translate("schedule.condition.threshold.train_holds",
Lang.translate("schedule.condition.threshold." + Lang.asId(ops.name()))), Lang.translate("schedule.condition.threshold." + Lang.asId(getOperator().name()))),
Lang.translate("schedule.condition.threshold.x_units_of_item", threshold, Lang.translate("schedule.condition.threshold.x_units_of_item", getThreshold(),
Lang.translate("schedule.condition.threshold.buckets"), Lang.translate("schedule.condition.threshold.buckets"),
compareStack.getItem() instanceof FilterItem compareStack.getItem() instanceof FilterItem
? Lang.translate("schedule.condition.threshold.matching_content") ? Lang.translate("schedule.condition.threshold.matching_content")
@ -80,10 +107,15 @@ public class FluidThresholdCondition extends CargoThresholdCondition {
} }
@Override @Override
public void setItem(ItemStack stack) { public void setItem(int slot, ItemStack stack) {
compareStack = stack; compareStack = stack;
} }
@Override
public ItemStack getItem(int slot) {
return compareStack;
}
@Override @Override
public ResourceLocation getId() { public ResourceLocation getId() {
return Create.asResource("fluid_threshold"); return Create.asResource("fluid_threshold");
@ -91,15 +123,12 @@ public class FluidThresholdCondition extends CargoThresholdCondition {
@Override @Override
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public void createWidgets(ScheduleScreen screen, public void initConfigurationWidgets(ModularGuiLineBuilder builder) {
List<Pair<GuiEventListener, BiConsumer<IScheduleInput, GuiEventListener>>> editorSubWidgets, super.initConfigurationWidgets(builder);
List<Integer> dividers, int x, int y) { builder.addSelectionScrollInput(71, 50, (i, l) -> {
super.createWidgets(screen, editorSubWidgets, dividers, x, y); i.forOptions(ImmutableList.of(Lang.translate("schedule.condition.threshold.buckets")))
.titled(null);
TranslatableComponent buckets = Lang.translate("schedule.condition.threshold.buckets"); }, "Measure");
Label label = new Label(x + 155, y + 52, buckets).withShadow();
label.text = buckets;
editorSubWidgets.add(Pair.of(label, (d, l) -> {
}));
} }
} }

View file

@ -1,14 +1,19 @@
package com.simibubi.create.content.logistics.trains.management.schedule.condition; package com.simibubi.create.content.logistics.trains.management.schedule.condition;
import com.simibubi.create.Create; import com.simibubi.create.Create;
import com.simibubi.create.content.logistics.trains.entity.Carriage;
import com.simibubi.create.content.logistics.trains.entity.Train;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.Pair; import com.simibubi.create.foundation.utility.Pair;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
public class IdleCargoCondition extends TimedWaitCondition { public class IdleCargoCondition extends TimedWaitCondition {
@Override @Override
public Pair<ItemStack, Component> getSummary() { public Pair<ItemStack, Component> getSummary() {
return Pair.of(ItemStack.EMPTY, Lang.translate("schedule.condition.idle_short", formatTime(true))); return Pair.of(ItemStack.EMPTY, Lang.translate("schedule.condition.idle_short", formatTime(true)));
@ -18,4 +23,13 @@ public class IdleCargoCondition extends TimedWaitCondition {
public ResourceLocation getId() { public ResourceLocation getId() {
return Create.asResource("idle"); return Create.asResource("idle");
} }
@Override
public boolean tickCompletion(Level level, Train train, CompoundTag context) {
int idleTime = Integer.MAX_VALUE;
for (Carriage carriage : train.carriages)
idleTime = Math.min(idleTime, carriage.storage.getTicksSinceLastExchange());
return idleTime > totalWaitTicks();
}
} }

View file

@ -1,36 +1,32 @@
package com.simibubi.create.content.logistics.trains.management.schedule.condition; package com.simibubi.create.content.logistics.trains.management.schedule.condition;
import java.util.List; import java.util.List;
import java.util.function.BiConsumer;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.simibubi.create.Create; import com.simibubi.create.Create;
import com.simibubi.create.content.logistics.item.filter.FilterItem; import com.simibubi.create.content.logistics.item.filter.FilterItem;
import com.simibubi.create.content.logistics.trains.management.schedule.IScheduleInput; import com.simibubi.create.content.logistics.trains.entity.Carriage;
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleScreen; import com.simibubi.create.content.logistics.trains.entity.Train;
import com.simibubi.create.foundation.gui.widget.Label; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder;
import com.simibubi.create.foundation.gui.widget.ScrollInput;
import com.simibubi.create.foundation.gui.widget.SelectionScrollInput;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.Pair;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.client.gui.components.events.GuiEventListener;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent; import net.minecraft.network.chat.TextComponent;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.items.IItemHandlerModifiable;
public class ItemThresholdCondition extends CargoThresholdCondition { public class ItemThresholdCondition extends CargoThresholdCondition {
public ItemStack stack = ItemStack.EMPTY; public ItemStack stack = ItemStack.EMPTY;
public boolean stacks;
@Override @Override
protected Component getUnit() { protected Component getUnit() {
return new TextComponent(stacks ? "\u25A4" : ""); return new TextComponent(inStacks() ? "\u25A4" : "");
} }
@Override @Override
@ -39,36 +35,78 @@ public class ItemThresholdCondition extends CargoThresholdCondition {
} }
@Override @Override
protected void write(CompoundTag tag) { protected boolean test(Level level, Train train) {
super.write(tag); Ops operator = getOperator();
int target = getThreshold();
boolean stacks = inStacks();
if (stack.isEmpty())
return true;
int foundItems = 0;
for (Carriage carriage : train.carriages) {
IItemHandlerModifiable items = carriage.storage.getItems();
for (int i = 0; i < items.getSlots(); i++) {
ItemStack stackInSlot = items.getStackInSlot(i);
if (!FilterItem.test(level, stackInSlot, stack))
continue;
if (stacks)
foundItems += stackInSlot.getCount() == stackInSlot.getMaxStackSize() ? 1 : 0;
else
foundItems += stackInSlot.getCount();
if (operator != Ops.GREATER && foundItems > target)
return false;
}
}
return operator.test(foundItems, target);
}
@Override
protected void writeAdditional(CompoundTag tag) {
super.writeAdditional(tag);
tag.put("Item", stack.serializeNBT()); tag.put("Item", stack.serializeNBT());
tag.putBoolean("Stacks", stacks);
} }
@Override @Override
protected void read(CompoundTag tag) { protected void readAdditional(CompoundTag tag) {
super.read(tag); super.readAdditional(tag);
stack = ItemStack.of(tag.getCompound("Item")); stack = ItemStack.of(tag.getCompound("Item"));
stacks = tag.getBoolean("Stacks");
} }
@Override @Override
public void setItem(ItemStack stack) { public boolean tickCompletion(Level level, Train train, CompoundTag context) {
return super.tickCompletion(level, train, context);
}
@Override
public void setItem(int slot, ItemStack stack) {
this.stack = stack; this.stack = stack;
} }
@Override
public ItemStack getItem(int slot) {
return stack;
}
@Override @Override
public List<Component> getTitleAs(String type) { public List<Component> getTitleAs(String type) {
return ImmutableList.of( return ImmutableList.of(
Lang.translate("schedule.condition.threshold.train_holds", Lang.translate("schedule.condition.threshold.train_holds",
Lang.translate("schedule.condition.threshold." + Lang.asId(ops.name()))), Lang.translate("schedule.condition.threshold." + Lang.asId(getOperator().name()))),
Lang.translate("schedule.condition.threshold.x_units_of_item", threshold, Lang.translate("schedule.condition.threshold.x_units_of_item", getThreshold(),
Lang.translate("schedule.condition.threshold." + (stacks ? "stacks" : "items")), Lang.translate("schedule.condition.threshold." + (inStacks() ? "stacks" : "items")),
stack.getItem() instanceof FilterItem ? Lang.translate("schedule.condition.threshold.matching_content") stack.getItem() instanceof FilterItem ? Lang.translate("schedule.condition.threshold.matching_content")
: stack.getHoverName()) : stack.getHoverName())
.withStyle(ChatFormatting.DARK_AQUA)); .withStyle(ChatFormatting.DARK_AQUA));
} }
private boolean inStacks() {
return intData("Measure") == 1;
}
@Override @Override
public ResourceLocation getId() { public ResourceLocation getId() {
return Create.asResource("item_threshold"); return Create.asResource("item_threshold");
@ -76,24 +114,12 @@ public class ItemThresholdCondition extends CargoThresholdCondition {
@Override @Override
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public void createWidgets(ScheduleScreen screen, public void initConfigurationWidgets(ModularGuiLineBuilder builder) {
List<Pair<GuiEventListener, BiConsumer<IScheduleInput, GuiEventListener>>> editorSubWidgets, super.initConfigurationWidgets(builder);
List<Integer> dividers, int x, int y) { builder.addSelectionScrollInput(71, 50, (i, l) -> {
super.createWidgets(screen, editorSubWidgets, dividers, x, y); i.forOptions(ImmutableList.of(Lang.translate("schedule.condition.threshold.items"),
Label label = new Label(x + 155, y + 52, new TextComponent(ops.formatted)).withShadow();
ScrollInput scrollInput = new SelectionScrollInput(x + 150, y + 48, 49, 16)
.forOptions(ImmutableList.of(Lang.translate("schedule.condition.threshold.items"),
Lang.translate("schedule.condition.threshold.stacks"))) Lang.translate("schedule.condition.threshold.stacks")))
.titled(Lang.translate("schedule.condition.threshold.item_measure")) .titled(Lang.translate("schedule.condition.threshold.item_measure"));
.writingTo(label) }, "Measure");
.setState(stacks ? 1 : 0);
editorSubWidgets.add(Pair.of(scrollInput, (dest, box) -> {
ItemThresholdCondition c = (ItemThresholdCondition) dest;
c.stacks = ((ScrollInput) box).getState() == 1;
}));
editorSubWidgets.add(Pair.of(label, (d, l) -> {
}));
} }
} }

View file

@ -0,0 +1,30 @@
package com.simibubi.create.content.logistics.trains.management.schedule.condition;
import com.simibubi.create.content.logistics.trains.entity.Train;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.Level;
public abstract class LazyTickedScheduleCondition extends ScheduleWaitCondition {
private int tickRate;
public LazyTickedScheduleCondition(int tickRate) {
this.tickRate = tickRate;
}
@Override
public boolean tickCompletion(Level level, Train train, CompoundTag context) {
int time = context.getInt("Time");
if (time % tickRate == 0) {
if (lazyTickCompletion(level, train, context))
return true;
time = 0;
}
context.putInt("Time", time + 1);
return false;
}
protected abstract boolean lazyTickCompletion(Level level, Train train, CompoundTag context);
}

View file

@ -0,0 +1,121 @@
package com.simibubi.create.content.logistics.trains.management.schedule.condition;
import java.util.List;
import com.google.common.collect.ImmutableList;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.Create;
import com.simibubi.create.content.logistics.RedstoneLinkNetworkHandler.Frequency;
import com.simibubi.create.content.logistics.trains.entity.Train;
import com.simibubi.create.foundation.gui.ModularGuiLineBuilder;
import com.simibubi.create.foundation.utility.Couple;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.Pair;
import net.minecraft.ChatFormatting;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
public class RedstoneLinkCondition extends ScheduleWaitCondition {
public Couple<Frequency> freq;
public RedstoneLinkCondition() {
freq = Couple.create(() -> Frequency.EMPTY);
}
@Override
public int slotsTargeted() {
return 2;
}
@Override
public Pair<ItemStack, Component> getSummary() {
return Pair.of(AllBlocks.REDSTONE_LINK.asStack(),
lowActivation() ? Lang.translate("schedule.condition.redstone_link_off")
: Lang.translate("schedule.condition.redstone_link_on"));
}
@Override
public List<Component> getSecondLineTooltip(int slot) {
return ImmutableList.of(Lang.translate(slot == 0 ? "logistics.firstFrequency" : "logistics.secondFrequency")
.withStyle(ChatFormatting.RED));
}
@Override
public List<Component> getTitleAs(String type) {
return ImmutableList.of(
Lang.translate("schedule.condition.redstone_link.frequency_" + (lowActivation() ? "unpowered" : "powered")),
new TextComponent(" #1 ").withStyle(ChatFormatting.GRAY)
.append(freq.getFirst()
.getStack()
.getHoverName()
.copy()
.withStyle(ChatFormatting.DARK_AQUA)),
new TextComponent(" #2 ").withStyle(ChatFormatting.GRAY)
.append(freq.getSecond()
.getStack()
.getHoverName()
.copy()
.withStyle(ChatFormatting.DARK_AQUA)));
}
@Override
public boolean tickCompletion(Level level, Train train, CompoundTag context) {
int lastChecked = context.contains("LastChecked") ? context.getInt("LastChecked") : -1;
int status = Create.REDSTONE_LINK_NETWORK_HANDLER.globalPowerVersion.get();
if (status == lastChecked)
return false;
context.putInt("LastChecked", status);
return Create.REDSTONE_LINK_NETWORK_HANDLER.hasAnyLoadedPower(freq) != lowActivation();
}
@Override
public void setItem(int slot, ItemStack stack) {
freq.set(slot == 0, Frequency.of(stack));
super.setItem(slot, stack);
}
@Override
public ItemStack getItem(int slot) {
return freq.get(slot == 0)
.getStack();
}
@Override
public ResourceLocation getId() {
return Create.asResource("redstone_link");
}
@Override
protected void writeAdditional(CompoundTag tag) {
tag.put("Frequency", freq.serializeEach(f -> f.getStack()
.serializeNBT()));
}
public boolean lowActivation() {
return intData("Inverted") == 1;
}
@Override
protected void readAdditional(CompoundTag tag) {
freq = Couple.deserializeEach(tag.getList("Frequency", Tag.TAG_COMPOUND), c -> Frequency.of(ItemStack.of(c)));
}
@Override
@OnlyIn(Dist.CLIENT)
public void initConfigurationWidgets(ModularGuiLineBuilder builder) {
builder.addSelectionScrollInput(20, 101,
(i, l) -> i.forOptions(Lang.translatedOptions("schedule.condition.redstone_link", "powered", "unpowered"))
.titled(Lang.translate("schedule.condition.redstone_link.frequency_state")),
"Inverted");
}
}

View file

@ -4,28 +4,23 @@ import java.util.function.Supplier;
import com.simibubi.create.Create; import com.simibubi.create.Create;
import com.simibubi.create.content.logistics.trains.entity.Train; import com.simibubi.create.content.logistics.trains.entity.Train;
import com.simibubi.create.content.logistics.trains.management.schedule.IScheduleInput;
import com.simibubi.create.content.logistics.trains.management.schedule.Schedule; import com.simibubi.create.content.logistics.trains.management.schedule.Schedule;
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleDataEntry;
import com.simibubi.create.foundation.utility.Pair; import com.simibubi.create.foundation.utility.Pair;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
public abstract class ScheduleWaitCondition implements IScheduleInput { public abstract class ScheduleWaitCondition extends ScheduleDataEntry {
protected abstract void write(CompoundTag tag); public abstract boolean tickCompletion(Level level, Train train, CompoundTag context);
protected abstract void read(CompoundTag tag);
public boolean tickCompletion(Level level, Train train, CompoundTag context) {
return false; // TODO: make abstract
}
public final CompoundTag write() { public final CompoundTag write() {
CompoundTag tag = new CompoundTag(); CompoundTag tag = new CompoundTag();
tag.putString("Id", getId().toString()); tag.putString("Id", getId().toString());
write(tag); tag.put("Data", data.copy());
writeAdditional(tag);
return tag; return tag;
} }
@ -43,7 +38,8 @@ public abstract class ScheduleWaitCondition implements IScheduleInput {
} }
ScheduleWaitCondition condition = supplier.get(); ScheduleWaitCondition condition = supplier.get();
condition.read(tag); condition.data = tag.getCompound("Data");
condition.readAdditional(tag);
return condition; return condition;
} }

View file

@ -12,15 +12,16 @@ import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
public class ScheduledDelay extends TimedWaitCondition { public class ScheduledDelay extends TimedWaitCondition {
@Override @Override
public Pair<ItemStack, Component> getSummary() { public Pair<ItemStack, Component> getSummary() {
return Pair.of(ItemStack.EMPTY, Lang.translate("schedule.condition.delay_short", formatTime(true))); return Pair.of(ItemStack.EMPTY, Lang.translate("schedule.condition.delay_short", formatTime(true)));
} }
@Override @Override
public boolean tickCompletion(Level level, Train train, CompoundTag context) { public boolean tickCompletion(Level level, Train train, CompoundTag context) {
int time = context.getInt("Time"); int time = context.getInt("Time");
if (time >= value * timeUnit.ticksPer) if (time >= totalWaitTicks())
return true; return true;
context.putInt("Time", time + 1); context.putInt("Time", time + 1);
return false; return false;

View file

@ -31,10 +31,10 @@ public class StationPoweredCondition extends ScheduleWaitCondition {
} }
@Override @Override
protected void write(CompoundTag tag) {} protected void writeAdditional(CompoundTag tag) {}
@Override @Override
protected void read(CompoundTag tag) {} protected void readAdditional(CompoundTag tag) {}
@Override @Override
public ResourceLocation getId() { public ResourceLocation getId() {

View file

@ -30,10 +30,10 @@ public class StationUnloadedCondition extends ScheduleWaitCondition {
} }
@Override @Override
protected void write(CompoundTag tag) {} protected void writeAdditional(CompoundTag tag) {}
@Override @Override
protected void read(CompoundTag tag) {} protected void readAdditional(CompoundTag tag) {}
@Override @Override
public ResourceLocation getId() { public ResourceLocation getId() {

View file

@ -1,15 +1,15 @@
package com.simibubi.create.content.logistics.trains.management.schedule.condition; package com.simibubi.create.content.logistics.trains.management.schedule.condition;
import java.util.List; import java.util.List;
import java.util.function.BiConsumer;
import org.apache.commons.lang3.mutable.MutableObject;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.Create; import com.simibubi.create.Create;
import com.simibubi.create.content.logistics.trains.entity.Train; import com.simibubi.create.content.logistics.trains.entity.Train;
import com.simibubi.create.content.logistics.trains.management.schedule.IScheduleInput; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder;
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleScreen;
import com.simibubi.create.foundation.gui.widget.Label; import com.simibubi.create.foundation.gui.widget.Label;
import com.simibubi.create.foundation.gui.widget.ScrollInput; import com.simibubi.create.foundation.gui.widget.ScrollInput;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
@ -17,11 +17,9 @@ import com.simibubi.create.foundation.utility.Pair;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.client.gui.GuiComponent; import net.minecraft.client.gui.GuiComponent;
import net.minecraft.client.gui.components.events.GuiEventListener;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent; import net.minecraft.network.chat.MutableComponent;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.Mth; import net.minecraft.util.Mth;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
@ -32,28 +30,24 @@ import net.minecraftforge.api.distmarker.OnlyIn;
public class TimeOfDayCondition extends ScheduleWaitCondition { public class TimeOfDayCondition extends ScheduleWaitCondition {
int hour;
int minute;
int gracePeriod;
public TimeOfDayCondition() { public TimeOfDayCondition() {
hour = 8; data.putInt("Hour", 8);
minute = 0; data.putInt("GracePeriod", 5);
gracePeriod = 5;
} }
@Override @Override
public boolean tickCompletion(Level level, Train train, CompoundTag context) { public boolean tickCompletion(Level level, Train train, CompoundTag context) {
int maxTickDiff = Math.max(20, gracePeriod * 60 * 20); int maxTickDiff = Math.max(20, intData("GracePeriod") * 60 * 20);
int dayTime = (int) (level.getDayTime() % 24000); int dayTime = (int) (level.getDayTime() % 24000);
int targetTicks = (int) (((hour + 18) % 24) * 1000 + (minute / 60f) * 100); int targetTicks = (int) (((intData("Hour") + 18) % 24) * 1000 + (intData("Minute") / 60f) * 100);
int diff = dayTime - targetTicks; int diff = dayTime - targetTicks;
return diff >= 0 && maxTickDiff >= diff; return diff >= 0 && maxTickDiff >= diff;
} }
@Override @Override
public Pair<ItemStack, Component> getSummary() { public Pair<ItemStack, Component> getSummary() {
return Pair.of(new ItemStack(Items.STRUCTURE_VOID), getDigitalDisplay(hour, minute, false)); return Pair.of(new ItemStack(Items.STRUCTURE_VOID),
getDigitalDisplay(intData("Hour"), intData("Minute"), false));
} }
public MutableComponent getDigitalDisplay(int hour, int minute, boolean doubleDigitHrs) { public MutableComponent getDigitalDisplay(int hour, int minute, boolean doubleDigitHrs) {
@ -64,15 +58,10 @@ public class TimeOfDayCondition extends ScheduleWaitCondition {
hour > 11 ? Lang.translate("generic.daytime.pm") : Lang.translate("generic.daytime.am")); hour > 11 ? Lang.translate("generic.daytime.pm") : Lang.translate("generic.daytime.am"));
} }
@Override
public List<Component> getSecondLineTooltip() {
return super.getSecondLineTooltip();
}
@Override @Override
public List<Component> getTitleAs(String type) { public List<Component> getTitleAs(String type) {
return ImmutableList.of(Lang.translate("schedule.condition.time_of_day.scheduled", return ImmutableList.of(Lang.translate("schedule.condition.time_of_day.scheduled",
getDigitalDisplay(hour, minute, false).withStyle(ChatFormatting.DARK_AQUA))); getDigitalDisplay(intData("Hour"), intData("Minute"), false).withStyle(ChatFormatting.DARK_AQUA)));
} }
public String twoDigits(int t) { public String twoDigits(int t) {
@ -84,25 +73,11 @@ public class TimeOfDayCondition extends ScheduleWaitCondition {
return Create.asResource("time_of_day"); return Create.asResource("time_of_day");
} }
@Override
protected void write(CompoundTag tag) {
tag.putInt("Hour", hour);
tag.putInt("Minute", minute);
tag.putInt("GracePeriod", gracePeriod);
}
@Override
protected void read(CompoundTag tag) {
hour = tag.getInt("Hour");
minute = tag.getInt("Minute");
gracePeriod = tag.getInt("GracePeriod");
}
@Override @Override
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public boolean renderSpecialIcon(PoseStack ms, int x, int y) { public boolean renderSpecialIcon(PoseStack ms, int x, int y) {
int displayHr = (hour + 12) % 24; int displayHr = (intData("Hour") + 12) % 24;
float progress = (displayHr * 60f + minute) / (24 * 60); float progress = (displayHr * 60f + intData("Minute")) / (24 * 60);
RenderSystem.setShaderTexture(0, RenderSystem.setShaderTexture(0,
new ResourceLocation("textures/item/clock_" + twoDigits(Mth.clamp((int) (progress * 64), 0, 63)) + ".png")); new ResourceLocation("textures/item/clock_" + twoDigits(Mth.clamp((int) (progress * 64), 0, 63)) + ".png"));
GuiComponent.blit(ms, x, y, 0, 0, 0, 16, 16, 16, 16); GuiComponent.blit(ms, x, y, 0, 0, 0, 16, 16, 16, 16);
@ -111,55 +86,60 @@ public class TimeOfDayCondition extends ScheduleWaitCondition {
@Override @Override
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public void createWidgets(ScheduleScreen screen, public void initConfigurationWidgets(ModularGuiLineBuilder builder) {
List<Pair<GuiEventListener, BiConsumer<IScheduleInput, GuiEventListener>>> editorSubWidgets, MutableObject<ScrollInput> minuteInput = new MutableObject<>();
List<Integer> dividers, int x, int y) { MutableObject<ScrollInput> hourInput = new MutableObject<>();
super.createWidgets(screen, editorSubWidgets, dividers, x, y); MutableObject<Label> timeLabel = new MutableObject<>();
Label timeLabel = new Label(x + 87, y + 52, new TextComponent("")).withShadow(); builder.addScrollInput(0, 16, (i, l) -> {
timeLabel.text = getDigitalDisplay(hour, minute, true); i.withRange(0, 24);
ScrollInput hourInput = new ScrollInput(x + 82, y + 48, 16, 16).withRange(0, 24); timeLabel.setValue(l);
ScrollInput minuteInput = new ScrollInput(x + 82 + 18, y + 48, 16, 16).withRange(0, 60); hourInput.setValue(i);
}, "Hour");
hourInput.titled(Lang.translate("generic.daytime.hour")) builder.addScrollInput(18, 16, (i, l) -> {
i.withRange(0, 60);
minuteInput.setValue(i);
l.visible = false;
}, "Minute");
builder.addScrollInput(68, 49, (i, l) -> {
i.withRange(0, 12)
.titled(Lang.translate("schedule.condition.time_of_day.grace_period"))
.format(t -> Lang.translate("schedule.condition.time_of_day.grace_period.format", t));
}, "GracePeriod");
hourInput.getValue()
.titled(Lang.translate("generic.daytime.hour"))
.calling(t -> { .calling(t -> {
hour = t; data.putInt("Hour", t);
timeLabel.text = getDigitalDisplay(hour, minute, true); timeLabel.getValue().text = getDigitalDisplay(t, minuteInput.getValue()
.getState(), true);
}) })
.withShiftStep(6) .writingTo(null)
.setState(hour); .withShiftStep(6);
minuteInput.titled(Lang.translate("generic.daytime.minute")) minuteInput.getValue()
.titled(Lang.translate("generic.daytime.minute"))
.calling(t -> { .calling(t -> {
minute = t; data.putInt("Minute", t);
timeLabel.text = getDigitalDisplay(hour, minute, true); timeLabel.getValue().text = getDigitalDisplay(hourInput.getValue()
.getState(), t, true);
}) })
.withShiftStep(15) .writingTo(null)
.setState(minute); .withShiftStep(15);
minuteInput.lockedTooltipX = hourInput.lockedTooltipX = x + 83 + 40;
minuteInput.lockedTooltipY = hourInput.lockedTooltipY = y + 55;
dividers.add(70); minuteInput.getValue().lockedTooltipX = hourInput.getValue().lockedTooltipX = -15;
minuteInput.getValue().lockedTooltipY = hourInput.getValue().lockedTooltipY = 35;
Label graceLabel = new Label(x + 155, y + 52, new TextComponent("")).withShadow(); hourInput.getValue()
graceLabel.text = Lang.translate("schedule.condition.time_of_day.grace_period.format", gracePeriod); .setState(intData("Hour"));
ScrollInput scrollInput = new ScrollInput(x + 150, y + 48, 49, 16).withRange(0, 12) minuteInput.getValue()
.titled(Lang.translate("schedule.condition.time_of_day.grace_period")) .setState(intData("Minute"))
.calling(t -> graceLabel.text = Lang.translate("schedule.condition.time_of_day.grace_period.format", t)) .onChanged();
.setState(gracePeriod);
editorSubWidgets.add(Pair.of(scrollInput, builder.customArea(0, 60);
(dest, box) -> ((TimeOfDayCondition) dest).gracePeriod = ((ScrollInput) box).getState())); builder.customArea(65, 56);
editorSubWidgets
.add(Pair.of(hourInput, (dest, box) -> ((TimeOfDayCondition) dest).hour = ((ScrollInput) box).getState()));
editorSubWidgets.add(
Pair.of(minuteInput, (dest, box) -> ((TimeOfDayCondition) dest).minute = ((ScrollInput) box).getState()));
editorSubWidgets.add(Pair.of(timeLabel, (d, l) -> {
}));
editorSubWidgets.add(Pair.of(graceLabel, (d, l) -> {
}));
} }
} }

View file

@ -1,22 +1,12 @@
package com.simibubi.create.content.logistics.trains.management.schedule.condition; package com.simibubi.create.content.logistics.trains.management.schedule.condition;
import java.util.List; import java.util.List;
import java.util.function.BiConsumer;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.simibubi.create.content.logistics.trains.management.schedule.IScheduleInput; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder;
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleScreen;
import com.simibubi.create.foundation.gui.widget.Label;
import com.simibubi.create.foundation.gui.widget.ScrollInput;
import com.simibubi.create.foundation.gui.widget.SelectionScrollInput;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.NBTHelper;
import com.simibubi.create.foundation.utility.Pair;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.client.gui.components.EditBox;
import net.minecraft.client.gui.components.events.GuiEventListener;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent; import net.minecraft.network.chat.TextComponent;
import net.minecraft.network.chat.TranslatableComponent; import net.minecraft.network.chat.TranslatableComponent;
@ -26,8 +16,6 @@ import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
public abstract class TimedWaitCondition extends ScheduleWaitCondition { public abstract class TimedWaitCondition extends ScheduleWaitCondition {
public TimedWaitCondition.TimeUnit timeUnit = TimeUnit.TICKS;
public int value;
public static enum TimeUnit { public static enum TimeUnit {
TICKS(1, "t", "generic.unit.ticks"), TICKS(1, "t", "generic.unit.ticks"),
@ -49,10 +37,19 @@ public abstract class TimedWaitCondition extends ScheduleWaitCondition {
} }
} }
public int totalWaitTicks() {
return getValue() * getUnit().ticksPer;
}
public TimedWaitCondition() {
data.putInt("Value", 5);
data.putInt("TimeUnit", TimeUnit.SECONDS.ordinal());
}
protected Component formatTime(boolean compact) { protected Component formatTime(boolean compact) {
if (compact) if (compact)
return new TextComponent(value + timeUnit.suffix); return new TextComponent(getValue() + getUnit().suffix);
return new TextComponent(value + " ").append(Lang.translate(timeUnit.key)); return new TextComponent(getValue() + " ").append(Lang.translate(getUnit().key));
} }
@Override @Override
@ -63,73 +60,39 @@ public abstract class TimedWaitCondition extends ScheduleWaitCondition {
.withStyle(ChatFormatting.DARK_AQUA)); .withStyle(ChatFormatting.DARK_AQUA));
} }
@Override
protected void write(CompoundTag tag) {
tag.putInt("Value", value);
NBTHelper.writeEnum(tag, "Unit", timeUnit);
}
@Override
protected void read(CompoundTag tag) {
value = tag.getInt("Value");
timeUnit = NBTHelper.readEnum(tag, "Unit", TimedWaitCondition.TimeUnit.class);
}
@Override @Override
public ItemStack getSecondLineIcon() { public ItemStack getSecondLineIcon() {
return new ItemStack(Items.REPEATER); return new ItemStack(Items.REPEATER);
} }
@Override @Override
public List<Component> getSecondLineTooltip() { public List<Component> getSecondLineTooltip(int slot) {
return ImmutableList.of(Lang.translate("generic.duration")); return ImmutableList.of(Lang.translate("generic.duration"));
} }
public int getValue() {
return intData("Value");
}
public TimeUnit getUnit() {
return enumData("TimeUnit", TimeUnit.class);
}
@Override @Override
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public void createWidgets(ScheduleScreen screen, public void initConfigurationWidgets(ModularGuiLineBuilder builder) {
List<Pair<GuiEventListener, BiConsumer<IScheduleInput, GuiEventListener>>> editorSubWidgets, builder.addScrollInput(0, 31, (i, l) -> {
List<Integer> dividers, int x, int y) { i.titled(Lang.translate("generic.duration"))
super.createWidgets(screen, editorSubWidgets, dividers, x, y); .withShiftStep(15)
.withRange(0, 121);
i.lockedTooltipX = -15;
i.lockedTooltipY = 35;
}, "Value");
EditBox editBox = new EditBox(screen.getFont(), x + 84, y + 52, 31, 10, new TextComponent(value + "")); builder.addSelectionScrollInput(36, 85, (i, l) -> {
editBox.setBordered(false); i.forOptions(TimeUnit.translatedOptions())
editBox.setValue(value + ""); .titled(Lang.translate("generic.timeUnit"));
editBox.setTextColor(0xFFFFFF); }, "TimeUnit");
editBox.changeFocus(false);
editBox.mouseClicked(0, 0, 0);
editBox.setFilter(s -> {
if (s.isEmpty())
return true;
try {
Integer.parseInt(s);
return true;
} catch (NumberFormatException e) {
return false;
}
});
dividers.add(40);
Label label = new Label(x + 125, y + 52, Lang.translate(timeUnit.key)).withShadow();
ScrollInput scrollInput =
new SelectionScrollInput(x + 120, y + 48, 79, 16).forOptions(TimeUnit.translatedOptions())
.titled(Lang.translate("generic.timeUnit"))
.writingTo(label)
.setState(timeUnit.ordinal());
editorSubWidgets.add(Pair.of(editBox, (dest, box) -> {
TimedWaitCondition c = (TimedWaitCondition) dest;
String text = ((EditBox) box).getValue();
if (text.isEmpty())
c.value = 0;
else
c.value = Integer.parseInt(text);
}));
editorSubWidgets.add(Pair.of(scrollInput, (dest, box) -> {
TimedWaitCondition c = (TimedWaitCondition) dest;
c.timeUnit = TimeUnit.values()[((ScrollInput) box).getState()];
}));
editorSubWidgets.add(Pair.of(label, (d, l) -> {
}));
} }
} }

View file

@ -14,7 +14,7 @@ import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items; import net.minecraft.world.item.Items;
public class ChangeTitleInstruction extends ScheduleInstructionWithEditBox { public class ChangeTitleInstruction extends TextScheduleInstruction {
@Override @Override
public Pair<ItemStack, Component> getSummary() { public Pair<ItemStack, Component> getSummary() {
@ -45,7 +45,7 @@ public class ChangeTitleInstruction extends ScheduleInstructionWithEditBox {
} }
@Override @Override
public List<Component> getSecondLineTooltip() { public List<Component> getSecondLineTooltip(int slot) {
return ImmutableList.of(Lang.translate("schedule.instruction.name_edit_box"), return ImmutableList.of(Lang.translate("schedule.instruction.name_edit_box"),
Lang.translate("schedule.instruction.name_edit_box_1") Lang.translate("schedule.instruction.name_edit_box_1")
.withStyle(ChatFormatting.GRAY), .withStyle(ChatFormatting.GRAY),

View file

@ -12,7 +12,6 @@ import com.simibubi.create.foundation.utility.Pair;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.client.gui.components.EditBox; import net.minecraft.client.gui.components.EditBox;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent; import net.minecraft.network.chat.TextComponent;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
@ -20,9 +19,7 @@ import net.minecraft.world.item.ItemStack;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
public class DestinationInstruction extends ScheduleInstructionWithEditBox { public class DestinationInstruction extends TextScheduleInstruction {
public boolean isWaypoint;
@Override @Override
public Pair<ItemStack, Component> getSummary() { public Pair<ItemStack, Component> getSummary() {
@ -31,21 +28,9 @@ public class DestinationInstruction extends ScheduleInstructionWithEditBox {
@Override @Override
public boolean supportsConditions() { public boolean supportsConditions() {
return !isWaypoint; return true;
} }
@Override
protected void write(CompoundTag tag) {
tag.putBoolean("Waypoint", isWaypoint);
super.write(tag);
}
@Override
protected void read(CompoundTag tag) {
isWaypoint = tag.getBoolean("Waypoint");
super.read(tag);
}
@Override @Override
public ResourceLocation getId() { public ResourceLocation getId() {
return Create.asResource("destination"); return Create.asResource("destination");
@ -61,7 +46,7 @@ public class DestinationInstruction extends ScheduleInstructionWithEditBox {
} }
@Override @Override
public List<Component> getSecondLineTooltip() { public List<Component> getSecondLineTooltip(int slot) {
return ImmutableList.of(Lang.translate("schedule.instruction.filter_edit_box"), return ImmutableList.of(Lang.translate("schedule.instruction.filter_edit_box"),
Lang.translate("schedule.instruction.filter_edit_box_1") Lang.translate("schedule.instruction.filter_edit_box_1")
.withStyle(ChatFormatting.GRAY), .withStyle(ChatFormatting.GRAY),

View file

@ -3,25 +3,22 @@ package com.simibubi.create.content.logistics.trains.management.schedule.destina
import java.util.function.Supplier; import java.util.function.Supplier;
import com.simibubi.create.Create; import com.simibubi.create.Create;
import com.simibubi.create.content.logistics.trains.management.schedule.IScheduleInput;
import com.simibubi.create.content.logistics.trains.management.schedule.Schedule; import com.simibubi.create.content.logistics.trains.management.schedule.Schedule;
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleDataEntry;
import com.simibubi.create.foundation.utility.Pair; import com.simibubi.create.foundation.utility.Pair;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
public abstract class ScheduleInstruction implements IScheduleInput { public abstract class ScheduleInstruction extends ScheduleDataEntry {
protected abstract void write(CompoundTag tag);
protected abstract void read(CompoundTag tag);
public abstract boolean supportsConditions(); public abstract boolean supportsConditions();
public final CompoundTag write() { public final CompoundTag write() {
CompoundTag tag = new CompoundTag(); CompoundTag tag = new CompoundTag();
tag.putString("Id", getId().toString()); tag.putString("Id", getId().toString());
write(tag); tag.put("Data", data.copy());
writeAdditional(tag);
return tag; return tag;
} }
@ -39,7 +36,8 @@ public abstract class ScheduleInstruction implements IScheduleInput {
} }
ScheduleInstruction scheduleDestination = supplier.get(); ScheduleInstruction scheduleDestination = supplier.get();
scheduleDestination.read(tag); scheduleDestination.data = tag.getCompound("Data");
scheduleDestination.readAdditional(tag);
return scheduleDestination; return scheduleDestination;
} }

View file

@ -1,69 +0,0 @@
package com.simibubi.create.content.logistics.trains.management.schedule.destination;
import java.util.List;
import java.util.function.BiConsumer;
import com.google.common.collect.ImmutableList;
import com.simibubi.create.content.logistics.trains.management.schedule.IScheduleInput;
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleScreen;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.Pair;
import net.minecraft.ChatFormatting;
import net.minecraft.client.gui.components.EditBox;
import net.minecraft.client.gui.components.events.GuiEventListener;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
public abstract class ScheduleInstructionWithEditBox extends ScheduleInstruction {
private String labelText = "";
protected String getLabelText() {
return labelText;
}
protected void setLabelText(String labelText) {
this.labelText = labelText;
}
@Override
protected void read(CompoundTag tag) {
labelText = tag.getString("Text");
}
@Override
protected void write(CompoundTag tag) {
tag.putString("Text", labelText);
}
@Override
public List<Component> getTitleAs(String type) {
return ImmutableList.of(Lang.translate("schedule." + type + "." + getId().getPath() + ".summary")
.withStyle(ChatFormatting.GOLD), Lang.translate("generic.in_quotes", new TextComponent(getLabelText())));
}
@Override
@OnlyIn(Dist.CLIENT)
public void createWidgets(ScheduleScreen screen,
List<Pair<GuiEventListener, BiConsumer<IScheduleInput, GuiEventListener>>> editorSubWidgets,
List<Integer> dividers, int x, int y) {
super.createWidgets(screen, editorSubWidgets, dividers, x, y);
EditBox editBox = new EditBox(screen.getFont(), x + 84, y + 52, 112, 10, new TextComponent(labelText));
editBox.setBordered(false);
editBox.setTextColor(0xFFFFFF);
editBox.setValue(labelText);
editBox.changeFocus(false);
editBox.mouseClicked(0, 0, 0);
editorSubWidgets.add(Pair.of(editBox,
(dest, box) -> ((ScheduleInstructionWithEditBox) dest).labelText = ((EditBox) box).getValue()));
}
@OnlyIn(Dist.CLIENT)
protected void modifyEditBox(EditBox box) {}
}

View file

@ -0,0 +1,37 @@
package com.simibubi.create.content.logistics.trains.management.schedule.destination;
import java.util.List;
import com.google.common.collect.ImmutableList;
import com.simibubi.create.foundation.gui.ModularGuiLineBuilder;
import com.simibubi.create.foundation.utility.Lang;
import net.minecraft.ChatFormatting;
import net.minecraft.client.gui.components.EditBox;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
public abstract class TextScheduleInstruction extends ScheduleInstruction {
protected String getLabelText() {
return textData("Text");
}
@Override
public List<Component> getTitleAs(String type) {
return ImmutableList.of(Lang.translate("schedule." + type + "." + getId().getPath() + ".summary")
.withStyle(ChatFormatting.GOLD), Lang.translate("generic.in_quotes", new TextComponent(getLabelText())));
}
@Override
@OnlyIn(Dist.CLIENT)
public void initConfigurationWidgets(ModularGuiLineBuilder builder) {
builder.addTextInput(0, 121, (e, t) -> modifyEditBox(e), "Text");
}
@OnlyIn(Dist.CLIENT)
protected void modifyEditBox(EditBox box) {}
}

View file

@ -19,7 +19,6 @@ import com.simibubi.create.foundation.tileEntity.IMergeableTE;
import com.simibubi.create.foundation.tileEntity.RemoveTileEntityPacket; import com.simibubi.create.foundation.tileEntity.RemoveTileEntityPacket;
import com.simibubi.create.foundation.tileEntity.SmartTileEntity; import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
import com.simibubi.create.foundation.utility.Debug;
import com.simibubi.create.foundation.utility.Pair; import com.simibubi.create.foundation.utility.Pair;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
@ -87,8 +86,6 @@ public class TrackTileEntity extends SmartTileEntity implements ITransformableTE
Vec3 bcEndAxis = bc.axes.getSecond(); Vec3 bcEndAxis = bc.axes.getSecond();
if (v.distanceTo(bcEndAxis) < 1 / 1024f || v.distanceTo(bcEndAxis.scale(-1)) < 1 / 1024f) if (v.distanceTo(bcEndAxis) < 1 / 1024f || v.distanceTo(bcEndAxis.scale(-1)) < 1 / 1024f)
level.setBlock(key, blockState.setValue(TrackBlock.HAS_TE, true), 3); level.setBlock(key, blockState.setValue(TrackBlock.HAS_TE, true), 3);
else
Debug.debugChat(v + " != " + bcEndAxis);
} }
BlockEntity blockEntity = level.getBlockEntity(key); BlockEntity blockEntity = level.getBlockEntity(key);

View file

@ -118,18 +118,17 @@ public abstract class AbstractSimiScreen extends Screen {
boolean keyPressed = super.keyPressed(keyCode, scanCode, modifiers); boolean keyPressed = super.keyPressed(keyCode, scanCode, modifiers);
if (keyPressed || getFocused() != null) if (keyPressed || getFocused() != null)
return keyPressed; return keyPressed;
InputConstants.Key mouseKey = InputConstants.getKey(keyCode, scanCode); InputConstants.Key mouseKey = InputConstants.getKey(keyCode, scanCode);
if (this.minecraft.options.keyInventory.isActiveAndMatches(mouseKey)) { if (this.minecraft.options.keyInventory.isActiveAndMatches(mouseKey)) {
this.onClose(); this.onClose();
return true; return true;
} }
return false; return false;
} }
protected void prepareFrame() { protected void prepareFrame() {}
}
protected void renderWindowBackground(PoseStack ms, int mouseX, int mouseY, float partialTicks) { protected void renderWindowBackground(PoseStack ms, int mouseX, int mouseY, float partialTicks) {
renderBackground(ms); renderBackground(ms);
@ -141,22 +140,22 @@ public abstract class AbstractSimiScreen extends Screen {
for (Widget widget : renderables) { for (Widget widget : renderables) {
if (widget instanceof AbstractSimiWidget simiWidget && simiWidget.isHoveredOrFocused()) { if (widget instanceof AbstractSimiWidget simiWidget && simiWidget.isHoveredOrFocused()) {
List<Component> tooltip = simiWidget.getToolTip(); List<Component> tooltip = simiWidget.getToolTip();
int ttx = simiWidget.lockedTooltipX; if (tooltip.isEmpty())
int tty = simiWidget.lockedTooltipY; continue;
if (!tooltip.isEmpty()) int ttx = simiWidget.lockedTooltipX == -1 ? mouseX : simiWidget.lockedTooltipX + simiWidget.x;
renderComponentTooltip(ms, tooltip, ttx == -1 ? mouseX : ttx, tty == -1 ? mouseY : tty); int tty = simiWidget.lockedTooltipY == -1 ? mouseY : simiWidget.lockedTooltipY + simiWidget.y;
renderComponentTooltip(ms, tooltip, ttx, tty);
} }
} }
} }
protected void endFrame() { protected void endFrame() {}
}
@Deprecated @Deprecated
protected void debugWindowArea(PoseStack matrixStack) { protected void debugWindowArea(PoseStack matrixStack) {
fill(matrixStack, guiLeft + windowWidth, guiTop + windowHeight, guiLeft, guiTop, 0xD3D3D3D3); fill(matrixStack, guiLeft + windowWidth, guiTop + windowHeight, guiLeft, guiTop, 0xD3D3D3D3);
} }
@Override @Override
public GuiEventListener getFocused() { public GuiEventListener getFocused() {
GuiEventListener focused = super.getFocused(); GuiEventListener focused = super.getFocused();

View file

@ -83,6 +83,7 @@ public enum AllGuiTextures implements ScreenElement {
DATA_GATHERER("display_link", 235, 162), DATA_GATHERER("display_link", 235, 162),
DATA_AREA_START("display_link", 0, 163, 2, 18), DATA_AREA_START("display_link", 0, 163, 2, 18),
DATA_AREA_SPEECH("display_link", 8, 163, 5, 18),
DATA_AREA("display_link", 3, 163, 1, 18), DATA_AREA("display_link", 3, 163, 1, 18),
DATA_AREA_END("display_link", 5, 163, 2, 18), DATA_AREA_END("display_link", 5, 163, 2, 18),
@ -112,9 +113,8 @@ public enum AllGuiTextures implements ScreenElement {
SCHEDULE_STRIP_END("schedule", 34, 239, 11, 16), SCHEDULE_STRIP_END("schedule", 34, 239, 11, 16),
SCHEDULE_STRIP_ACTION("schedule", 209, 239, 11, 16), SCHEDULE_STRIP_ACTION("schedule", 209, 239, 11, 16),
SCHEDULE_EDITOR("schedule_2", 256, 89), SCHEDULE_EDITOR("schedule_2", 256, 89),
SCHEDULE_EDITOR_ADDITIONAL_SLOT("schedule_2", 55, 47, 32, 18),
SCHEDULE_EDITOR_INACTIVE_SLOT("schedule_2", 0, 91, 18, 18), SCHEDULE_EDITOR_INACTIVE_SLOT("schedule_2", 0, 91, 18, 18),
SCHEDULE_EDITOR_SECOND_LINE("schedule_2", 20, 91, 124, 18),
SCHEDULE_EDITOR_DIVIDER("schedule_2", 145, 91, 4, 18),
SCHEDULE_POINTER("schedule", 185, 239, 21, 16), SCHEDULE_POINTER("schedule", 185, 239, 21, 16),
SCHEDULE_POINTER_OFFSCREEN("schedule", 171, 239, 13, 16), SCHEDULE_POINTER_OFFSCREEN("schedule", 171, 239, 13, 16),

View file

@ -0,0 +1,115 @@
package com.simibubi.create.foundation.gui;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.foundation.gui.widget.ScrollInput;
import com.simibubi.create.foundation.gui.widget.TooltipArea;
import com.simibubi.create.foundation.utility.Couple;
import com.simibubi.create.foundation.utility.Pair;
import net.minecraft.client.gui.components.AbstractWidget;
import net.minecraft.client.gui.components.EditBox;
import net.minecraft.client.gui.components.Widget;
import net.minecraft.client.gui.components.events.GuiEventListener;
import net.minecraft.client.gui.narration.NarratableEntry;
import net.minecraft.nbt.CompoundTag;
public class ModularGuiLine {
List<Pair<AbstractWidget, String>> widgets;
List<Couple<Integer>> customBoxes;
boolean speechBubble;
public ModularGuiLine() {
widgets = new ArrayList<>();
customBoxes = new ArrayList<>();
speechBubble = false;
}
public void renderWidgetBG(int guiLeft, PoseStack ms) {
boolean first = true;
if (!customBoxes.isEmpty()) {
for (Couple<Integer> couple : customBoxes) {
int x = couple.getFirst() + guiLeft;
int width = couple.getSecond();
box(ms, x, width, first & speechBubble);
first = false;
}
return;
}
for (Pair<AbstractWidget, String> pair : widgets) {
if (pair.getSecond()
.equals("Dummy"))
continue;
AbstractWidget aw = pair.getFirst();
int x = aw.x;
int width = aw.getWidth();
if (aw instanceof EditBox) {
x -= 5;
width += 9;
}
box(ms, x, width, first & speechBubble);
first = false;
}
}
private void box(PoseStack ms, int x, int width, boolean b) {
UIRenderHelper.drawStretched(ms, x, 0, width, 18, 0, AllGuiTextures.DATA_AREA);
if (b)
AllGuiTextures.DATA_AREA_SPEECH.render(ms, x - 3, 0);
else
AllGuiTextures.DATA_AREA_START.render(ms, x, 0);
AllGuiTextures.DATA_AREA_END.render(ms, x + width - 2, 0);
}
public void saveValues(CompoundTag data) {
for (Pair<AbstractWidget, String> pair : widgets) {
AbstractWidget w = pair.getFirst();
String key = pair.getSecond();
if (w instanceof EditBox eb)
data.putString(key, eb.getValue());
if (w instanceof ScrollInput si)
data.putInt(key, si.getState());
}
}
@SuppressWarnings("unchecked")
public <T extends GuiEventListener & Widget & NarratableEntry> void loadValues(CompoundTag data,
Consumer<T> addRenderable, Consumer<T> addRenderableOnly) {
for (Pair<AbstractWidget, String> pair : widgets) {
AbstractWidget w = pair.getFirst();
String key = pair.getSecond();
if (w instanceof EditBox eb)
eb.setValue(data.getString(key));
if (w instanceof ScrollInput si)
si.setState(data.getInt(key));
if (w instanceof TooltipArea)
addRenderableOnly.accept((T) w);
else
addRenderable.accept((T) w);
}
}
public void forEach(Consumer<GuiEventListener> callback) {
widgets.forEach(p -> callback.accept(p.getFirst()));
}
public void clear() {
widgets.clear();
customBoxes.clear();
}
public void add(Pair<AbstractWidget, String> pair) {
widgets.add(pair);
}
}

View file

@ -0,0 +1,91 @@
package com.simibubi.create.foundation.gui;
import java.util.function.BiConsumer;
import com.simibubi.create.foundation.gui.widget.Label;
import com.simibubi.create.foundation.gui.widget.ScrollInput;
import com.simibubi.create.foundation.gui.widget.SelectionScrollInput;
import com.simibubi.create.foundation.gui.widget.TooltipArea;
import com.simibubi.create.foundation.utility.Couple;
import com.simibubi.create.foundation.utility.Pair;
import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.components.EditBox;
import net.minecraft.network.chat.TextComponent;
public class ModularGuiLineBuilder {
private ModularGuiLine target;
private Font font;
private int x;
private int y;
public ModularGuiLineBuilder(Font font, ModularGuiLine target, int x, int y) {
this.font = font;
this.target = target;
this.x = x;
this.y = y;
}
public ModularGuiLineBuilder addScrollInput(int x, int width, BiConsumer<ScrollInput, Label> inputTransform,
String dataKey) {
ScrollInput input = new ScrollInput(x + this.x, y - 4, width, 18);
addScrollInput(input, inputTransform, dataKey);
return this;
}
public ModularGuiLineBuilder addSelectionScrollInput(int x, int width,
BiConsumer<SelectionScrollInput, Label> inputTransform, String dataKey) {
SelectionScrollInput input = new SelectionScrollInput(x + this.x, y - 4, width, 18);
addScrollInput(input, inputTransform, dataKey);
return this;
}
public ModularGuiLineBuilder customArea(int x, int width) {
target.customBoxes.add(Couple.create(x, width));
return this;
}
public ModularGuiLineBuilder speechBubble() {
target.speechBubble = true;
return this;
}
private <T extends ScrollInput> void addScrollInput(T input, BiConsumer<T, Label> inputTransform, String dataKey) {
Label label = new Label(input.x + 5, y, TextComponent.EMPTY);
label.withShadow();
inputTransform.accept(input, label);
input.writingTo(label);
target.add(Pair.of(label, "Dummy"));
target.add(Pair.of(input, dataKey));
}
public ModularGuiLineBuilder addIntegerTextInput(int x, int width, BiConsumer<EditBox, TooltipArea> inputTransform,
String dataKey) {
return addTextInput(x, width, inputTransform.andThen((editBox, $) -> editBox.setFilter(s -> {
if (s.isEmpty())
return true;
try {
Integer.parseInt(s);
return true;
} catch (NumberFormatException e) {
return false;
}
})), dataKey);
}
public ModularGuiLineBuilder addTextInput(int x, int width, BiConsumer<EditBox, TooltipArea> inputTransform,
String dataKey) {
EditBox input = new EditBox(font, x + this.x + 5, y, width - 9, 8, TextComponent.EMPTY);
input.setBordered(false);
input.setTextColor(0xffffff);
input.changeFocus(false);
input.mouseClicked(0, 0, 0);
TooltipArea tooltipArea = new TooltipArea(this.x + x, y - 4, width, 18);
inputTransform.accept(input, tooltipArea);
target.add(Pair.of(input, dataKey));
target.add(Pair.of(tooltipArea, "Dummy"));
return this;
}
}

View file

@ -111,15 +111,16 @@ public abstract class AbstractSimiContainerScreen<T extends AbstractContainerMen
// values instead // values instead
} }
protected void renderForeground(PoseStack matrixStack, int mouseX, int mouseY, float partialTicks) { protected void renderForeground(PoseStack ms, int mouseX, int mouseY, float partialTicks) {
renderTooltip(matrixStack, mouseX, mouseY); renderTooltip(ms, mouseX, mouseY);
for (Widget widget : renderables) { for (Widget widget : renderables) {
if (widget instanceof AbstractSimiWidget simiWidget && simiWidget.isHoveredOrFocused()) { if (widget instanceof AbstractSimiWidget simiWidget && simiWidget.isHoveredOrFocused()) {
List<Component> tooltip = simiWidget.getToolTip(); List<Component> tooltip = simiWidget.getToolTip();
int ttx = simiWidget.lockedTooltipX; if (tooltip.isEmpty())
int tty = simiWidget.lockedTooltipY; continue;
if (!tooltip.isEmpty()) int ttx = simiWidget.lockedTooltipX == -1 ? mouseX : simiWidget.lockedTooltipX + simiWidget.x;
renderComponentTooltip(matrixStack, tooltip, ttx == -1 ? mouseX : ttx, tty == -1 ? mouseY : tty); int tty = simiWidget.lockedTooltipY == -1 ? mouseY : simiWidget.lockedTooltipY + simiWidget.y;
renderComponentTooltip(ms, tooltip, ttx, tty);
} }
} }
} }

View file

@ -21,6 +21,7 @@ public class ScrollInput extends AbstractSimiWidget {
protected final Component shiftScrollsFaster = Lang.translate("gui.scrollInput.shiftScrollsFaster"); protected final Component shiftScrollsFaster = Lang.translate("gui.scrollInput.shiftScrollsFaster");
protected Label displayLabel; protected Label displayLabel;
protected boolean inverted; protected boolean inverted;
protected Function<Integer, Component> formatter;
protected int min, max; protected int min, max;
protected int shiftStep; protected int shiftStep;
@ -33,12 +34,13 @@ public class ScrollInput extends AbstractSimiWidget {
max = 1; max = 1;
shiftStep = 5; shiftStep = 5;
step = standardStep(); step = standardStep();
formatter = i -> new TextComponent(String.valueOf(i));
} }
public Function<StepContext, Integer> standardStep() { public Function<StepContext, Integer> standardStep() {
return c -> c.shift ? shiftStep : 1; return c -> c.shift ? shiftStep : 1;
} }
public ScrollInput inverted() { public ScrollInput inverted() {
inverted = true; inverted = true;
return this; return this;
@ -54,7 +56,12 @@ public class ScrollInput extends AbstractSimiWidget {
this.onScroll = onScroll; this.onScroll = onScroll;
return this; return this;
} }
public ScrollInput format(Function<Integer, Component> formatter) {
this.formatter = formatter;
return this;
}
public ScrollInput removeCallback() { public ScrollInput removeCallback() {
this.onScroll = null; this.onScroll = null;
return this; return this;
@ -73,7 +80,8 @@ public class ScrollInput extends AbstractSimiWidget {
public ScrollInput writingTo(Label label) { public ScrollInput writingTo(Label label) {
this.displayLabel = label; this.displayLabel = label;
writeToLabel(); if (label != null)
writeToLabel();
return this; return this;
} }
@ -99,7 +107,7 @@ public class ScrollInput extends AbstractSimiWidget {
public boolean mouseScrolled(double mouseX, double mouseY, double delta) { public boolean mouseScrolled(double mouseX, double mouseY, double delta) {
if (inverted) if (inverted)
delta *= -1; delta *= -1;
StepContext context = new StepContext(); StepContext context = new StepContext();
context.control = AllKeys.ctrlDown(); context.control = AllKeys.ctrlDown();
context.shift = AllKeys.shiftDown(); context.shift = AllKeys.shiftDown();
@ -138,14 +146,19 @@ public class ScrollInput extends AbstractSimiWidget {
} }
protected void writeToLabel() { protected void writeToLabel() {
displayLabel.text = new TextComponent(String.valueOf(state)); displayLabel.text = formatter.apply(state);
} }
protected void updateTooltip() { protected void updateTooltip() {
toolTip.clear(); toolTip.clear();
toolTip.add(title.plainCopy().withStyle(s -> s.withColor(HEADER_RGB))); if (title == null)
toolTip.add(scrollToModify.plainCopy().withStyle(ChatFormatting.ITALIC, ChatFormatting.DARK_GRAY)); return;
toolTip.add(shiftScrollsFaster.plainCopy().withStyle(ChatFormatting.ITALIC, ChatFormatting.DARK_GRAY)); toolTip.add(title.plainCopy()
.withStyle(s -> s.withColor(HEADER_RGB)));
toolTip.add(scrollToModify.plainCopy()
.withStyle(ChatFormatting.ITALIC, ChatFormatting.DARK_GRAY));
toolTip.add(shiftScrollsFaster.plainCopy()
.withStyle(ChatFormatting.ITALIC, ChatFormatting.DARK_GRAY));
} }
} }

View file

@ -24,18 +24,16 @@ public class SelectionScrollInput extends ScrollInput {
public ScrollInput forOptions(List<? extends Component> options) { public ScrollInput forOptions(List<? extends Component> options) {
this.options = options; this.options = options;
this.max = options.size(); this.max = options.size();
format(options::get);
updateTooltip(); updateTooltip();
return this; return this;
} }
@Override
protected void writeToLabel() {
displayLabel.text = options.get(state);
}
@Override @Override
protected void updateTooltip() { protected void updateTooltip() {
toolTip.clear(); toolTip.clear();
if (title == null)
return;
toolTip.add(title.plainCopy() toolTip.add(title.plainCopy()
.withStyle(s -> s.withColor(HEADER_RGB))); .withStyle(s -> s.withColor(HEADER_RGB)));
int min = Math.min(this.max - 16, state - 7); int min = Math.min(this.max - 16, state - 7);

View file

@ -14,6 +14,7 @@ import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
import com.simibubi.create.foundation.tileEntity.behaviour.BehaviourType; import com.simibubi.create.foundation.tileEntity.behaviour.BehaviourType;
import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform; import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform;
import com.simibubi.create.foundation.utility.Couple;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
@ -109,8 +110,8 @@ public class LinkBehaviour extends TileEntityBehaviour implements IRedstoneLinka
} }
@Override @Override
public Pair<Frequency, Frequency> getNetworkKey() { public Couple<Frequency> getNetworkKey() {
return Pair.of(frequencyFirst, frequencyLast); return Couple.create(frequencyFirst, frequencyLast);
} }
@Override @Override

View file

@ -599,10 +599,10 @@
"create.schedule.condition.time_of_day.digital_format": "%1$s:%3$s %4$s", "create.schedule.condition.time_of_day.digital_format": "%1$s:%3$s %4$s",
"create.schedule.condition.time_of_day.grace_period": "Grace Period", "create.schedule.condition.time_of_day.grace_period": "Grace Period",
"create.schedule.condition.time_of_day.grace_period.format": "+%1$s Hrs.", "create.schedule.condition.time_of_day.grace_period.format": "+%1$s Hrs.",
"create.schedule.condition.threshold.train_holds": "Train Holds %1$s", "create.schedule.condition.threshold.train_holds": "Train holds %1$s",
"create.schedule.condition.threshold.greater": "More than", "create.schedule.condition.threshold.greater": "more than",
"create.schedule.condition.threshold.less": "Less than", "create.schedule.condition.threshold.less": "less than",
"create.schedule.condition.threshold.equal": "Exactly", "create.schedule.condition.threshold.equal": "exactly",
"create.schedule.condition.threshold.x_units_of_item": "%1$s %2$s of %3$s", "create.schedule.condition.threshold.x_units_of_item": "%1$s %2$s of %3$s",
"create.schedule.condition.threshold.matching_content": "Matching Content", "create.schedule.condition.threshold.matching_content": "Matching Content",
"create.schedule.condition.threshold.item_measure": "Item Measure", "create.schedule.condition.threshold.item_measure": "Item Measure",
@ -613,6 +613,14 @@
"create.schedule.condition.threshold.place_item_2": "Filters can be used", "create.schedule.condition.threshold.place_item_2": "Filters can be used",
"create.schedule.condition.fluid_threshold": "Fluid Cargo Condition", "create.schedule.condition.fluid_threshold": "Fluid Cargo Condition",
"create.schedule.condition.item_threshold": "Item Cargo Condition", "create.schedule.condition.item_threshold": "Item Cargo Condition",
"create.schedule.condition.redstone_link": "Redstone Link",
"create.schedule.condition.redstone_link_on": "Link On",
"create.schedule.condition.redstone_link_off": "Link Off",
"create.schedule.condition.redstone_link.powered": "Powered",
"create.schedule.condition.redstone_link.unpowered": "Not powered",
"create.schedule.condition.redstone_link.frequency_state": "Frequency state:",
"create.schedule.condition.redstone_link.frequency_powered": "Frequency powered:",
"create.schedule.condition.redstone_link.frequency_unpowered": "Frequency not powered:",
"create.schedule.loop": "Loop Forever", "create.schedule.loop": "Loop Forever",
"create.schedule.loop1": "Schedule starts over", "create.schedule.loop1": "Schedule starts over",
"create.schedule.loop2": "when completed", "create.schedule.loop2": "when completed",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2 KiB