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

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.grace_period": "Grace Period",
"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.greater": "More than",
"create.schedule.condition.threshold.less": "Less than",
"create.schedule.condition.threshold.equal": "Exactly",
"create.schedule.condition.threshold.train_holds": "Train holds %1$s",
"create.schedule.condition.threshold.greater": "more than",
"create.schedule.condition.threshold.less": "less than",
"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.matching_content": "Matching Content",
"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.fluid_threshold": "Fluid 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.loop1": "Schedule starts over",
"create.schedule.loop2": "when completed",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 919",
"_": "Missing Localizations: 927",
"_": "->------------------------] 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.grace_period": "UNLOCALIZED: Grace Period",
"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.greater": "UNLOCALIZED: More than",
"create.schedule.condition.threshold.less": "UNLOCALIZED: Less than",
"create.schedule.condition.threshold.equal": "UNLOCALIZED: Exactly",
"create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train holds %1$s",
"create.schedule.condition.threshold.greater": "UNLOCALIZED: more than",
"create.schedule.condition.threshold.less": "UNLOCALIZED: less than",
"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.matching_content": "UNLOCALIZED: Matching Content",
"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.fluid_threshold": "UNLOCALIZED: Fluid 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.loop1": "UNLOCALIZED: Schedule starts over",
"create.schedule.loop2": "UNLOCALIZED: when completed",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 569",
"_": "Missing Localizations: 577",
"_": "->------------------------] 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.grace_period": "UNLOCALIZED: Grace Period",
"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.greater": "UNLOCALIZED: More than",
"create.schedule.condition.threshold.less": "UNLOCALIZED: Less than",
"create.schedule.condition.threshold.equal": "UNLOCALIZED: Exactly",
"create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train holds %1$s",
"create.schedule.condition.threshold.greater": "UNLOCALIZED: more than",
"create.schedule.condition.threshold.less": "UNLOCALIZED: less than",
"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.matching_content": "UNLOCALIZED: Matching Content",
"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.fluid_threshold": "UNLOCALIZED: Fluid 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.loop1": "UNLOCALIZED: Schedule starts over",
"create.schedule.loop2": "UNLOCALIZED: when completed",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 233",
"_": "Missing Localizations: 241",
"_": "->------------------------] 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.grace_period": "UNLOCALIZED: Grace Period",
"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.greater": "UNLOCALIZED: More than",
"create.schedule.condition.threshold.less": "UNLOCALIZED: Less than",
"create.schedule.condition.threshold.equal": "UNLOCALIZED: Exactly",
"create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train holds %1$s",
"create.schedule.condition.threshold.greater": "UNLOCALIZED: more than",
"create.schedule.condition.threshold.less": "UNLOCALIZED: less than",
"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.matching_content": "UNLOCALIZED: Matching Content",
"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.fluid_threshold": "UNLOCALIZED: Fluid 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.loop1": "UNLOCALIZED: Schedule starts over",
"create.schedule.loop2": "UNLOCALIZED: when completed",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 1807",
"_": "Missing Localizations: 1815",
"_": "->------------------------] 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.grace_period": "UNLOCALIZED: Grace Period",
"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.greater": "UNLOCALIZED: More than",
"create.schedule.condition.threshold.less": "UNLOCALIZED: Less than",
"create.schedule.condition.threshold.equal": "UNLOCALIZED: Exactly",
"create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train holds %1$s",
"create.schedule.condition.threshold.greater": "UNLOCALIZED: more than",
"create.schedule.condition.threshold.less": "UNLOCALIZED: less than",
"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.matching_content": "UNLOCALIZED: Matching Content",
"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.fluid_threshold": "UNLOCALIZED: Fluid 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.loop1": "UNLOCALIZED: Schedule starts over",
"create.schedule.loop2": "UNLOCALIZED: when completed",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 1496",
"_": "Missing Localizations: 1504",
"_": "->------------------------] 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.grace_period": "UNLOCALIZED: Grace Period",
"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.greater": "UNLOCALIZED: More than",
"create.schedule.condition.threshold.less": "UNLOCALIZED: Less than",
"create.schedule.condition.threshold.equal": "UNLOCALIZED: Exactly",
"create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train holds %1$s",
"create.schedule.condition.threshold.greater": "UNLOCALIZED: more than",
"create.schedule.condition.threshold.less": "UNLOCALIZED: less than",
"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.matching_content": "UNLOCALIZED: Matching Content",
"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.fluid_threshold": "UNLOCALIZED: Fluid 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.loop1": "UNLOCALIZED: Schedule starts over",
"create.schedule.loop2": "UNLOCALIZED: when completed",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 235",
"_": "Missing Localizations: 243",
"_": "->------------------------] 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.grace_period": "UNLOCALIZED: Grace Period",
"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.greater": "UNLOCALIZED: More than",
"create.schedule.condition.threshold.less": "UNLOCALIZED: Less than",
"create.schedule.condition.threshold.equal": "UNLOCALIZED: Exactly",
"create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train holds %1$s",
"create.schedule.condition.threshold.greater": "UNLOCALIZED: more than",
"create.schedule.condition.threshold.less": "UNLOCALIZED: less than",
"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.matching_content": "UNLOCALIZED: Matching Content",
"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.fluid_threshold": "UNLOCALIZED: Fluid 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.loop1": "UNLOCALIZED: Schedule starts over",
"create.schedule.loop2": "UNLOCALIZED: when completed",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 235",
"_": "Missing Localizations: 243",
"_": "->------------------------] 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.grace_period": "UNLOCALIZED: Grace Period",
"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.greater": "UNLOCALIZED: More than",
"create.schedule.condition.threshold.less": "UNLOCALIZED: Less than",
"create.schedule.condition.threshold.equal": "UNLOCALIZED: Exactly",
"create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train holds %1$s",
"create.schedule.condition.threshold.greater": "UNLOCALIZED: more than",
"create.schedule.condition.threshold.less": "UNLOCALIZED: less than",
"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.matching_content": "UNLOCALIZED: Matching Content",
"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.fluid_threshold": "UNLOCALIZED: Fluid 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.loop1": "UNLOCALIZED: Schedule starts over",
"create.schedule.loop2": "UNLOCALIZED: when completed",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 2159",
"_": "Missing Localizations: 2167",
"_": "->------------------------] 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.grace_period": "UNLOCALIZED: Grace Period",
"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.greater": "UNLOCALIZED: More than",
"create.schedule.condition.threshold.less": "UNLOCALIZED: Less than",
"create.schedule.condition.threshold.equal": "UNLOCALIZED: Exactly",
"create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train holds %1$s",
"create.schedule.condition.threshold.greater": "UNLOCALIZED: more than",
"create.schedule.condition.threshold.less": "UNLOCALIZED: less than",
"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.matching_content": "UNLOCALIZED: Matching Content",
"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.fluid_threshold": "UNLOCALIZED: Fluid 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.loop1": "UNLOCALIZED: Schedule starts over",
"create.schedule.loop2": "UNLOCALIZED: when completed",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 608",
"_": "Missing Localizations: 616",
"_": "->------------------------] 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.grace_period": "UNLOCALIZED: Grace Period",
"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.greater": "UNLOCALIZED: More than",
"create.schedule.condition.threshold.less": "UNLOCALIZED: Less than",
"create.schedule.condition.threshold.equal": "UNLOCALIZED: Exactly",
"create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train holds %1$s",
"create.schedule.condition.threshold.greater": "UNLOCALIZED: more than",
"create.schedule.condition.threshold.less": "UNLOCALIZED: less than",
"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.matching_content": "UNLOCALIZED: Matching Content",
"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.fluid_threshold": "UNLOCALIZED: Fluid 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.loop1": "UNLOCALIZED: Schedule starts over",
"create.schedule.loop2": "UNLOCALIZED: when completed",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 1103",
"_": "Missing Localizations: 1111",
"_": "->------------------------] 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.grace_period": "UNLOCALIZED: Grace Period",
"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.greater": "UNLOCALIZED: More than",
"create.schedule.condition.threshold.less": "UNLOCALIZED: Less than",
"create.schedule.condition.threshold.equal": "UNLOCALIZED: Exactly",
"create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train holds %1$s",
"create.schedule.condition.threshold.greater": "UNLOCALIZED: more than",
"create.schedule.condition.threshold.less": "UNLOCALIZED: less than",
"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.matching_content": "UNLOCALIZED: Matching Content",
"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.fluid_threshold": "UNLOCALIZED: Fluid 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.loop1": "UNLOCALIZED: Schedule starts over",
"create.schedule.loop2": "UNLOCALIZED: when completed",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 1781",
"_": "Missing Localizations: 1789",
"_": "->------------------------] 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.grace_period": "UNLOCALIZED: Grace Period",
"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.greater": "UNLOCALIZED: More than",
"create.schedule.condition.threshold.less": "UNLOCALIZED: Less than",
"create.schedule.condition.threshold.equal": "UNLOCALIZED: Exactly",
"create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train holds %1$s",
"create.schedule.condition.threshold.greater": "UNLOCALIZED: more than",
"create.schedule.condition.threshold.less": "UNLOCALIZED: less than",
"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.matching_content": "UNLOCALIZED: Matching Content",
"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.fluid_threshold": "UNLOCALIZED: Fluid 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.loop1": "UNLOCALIZED: Schedule starts over",
"create.schedule.loop2": "UNLOCALIZED: when completed",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 236",
"_": "Missing Localizations: 244",
"_": "->------------------------] 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.grace_period": "UNLOCALIZED: Grace Period",
"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.greater": "UNLOCALIZED: More than",
"create.schedule.condition.threshold.less": "UNLOCALIZED: Less than",
"create.schedule.condition.threshold.equal": "UNLOCALIZED: Exactly",
"create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train holds %1$s",
"create.schedule.condition.threshold.greater": "UNLOCALIZED: more than",
"create.schedule.condition.threshold.less": "UNLOCALIZED: less than",
"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.matching_content": "UNLOCALIZED: Matching Content",
"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.fluid_threshold": "UNLOCALIZED: Fluid 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.loop1": "UNLOCALIZED: Schedule starts over",
"create.schedule.loop2": "UNLOCALIZED: when completed",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 613",
"_": "Missing Localizations: 621",
"_": "->------------------------] 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.grace_period": "UNLOCALIZED: Grace Period",
"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.greater": "UNLOCALIZED: More than",
"create.schedule.condition.threshold.less": "UNLOCALIZED: Less than",
"create.schedule.condition.threshold.equal": "UNLOCALIZED: Exactly",
"create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train holds %1$s",
"create.schedule.condition.threshold.greater": "UNLOCALIZED: more than",
"create.schedule.condition.threshold.less": "UNLOCALIZED: less than",
"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.matching_content": "UNLOCALIZED: Matching Content",
"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.fluid_threshold": "UNLOCALIZED: Fluid 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.loop1": "UNLOCALIZED: Schedule starts over",
"create.schedule.loop2": "UNLOCALIZED: when completed",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 233",
"_": "Missing Localizations: 241",
"_": "->------------------------] 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.grace_period": "UNLOCALIZED: Grace Period",
"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.greater": "UNLOCALIZED: More than",
"create.schedule.condition.threshold.less": "UNLOCALIZED: Less than",
"create.schedule.condition.threshold.equal": "UNLOCALIZED: Exactly",
"create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train holds %1$s",
"create.schedule.condition.threshold.greater": "UNLOCALIZED: more than",
"create.schedule.condition.threshold.less": "UNLOCALIZED: less than",
"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.matching_content": "UNLOCALIZED: Matching Content",
"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.fluid_threshold": "UNLOCALIZED: Fluid 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.loop1": "UNLOCALIZED: Schedule starts over",
"create.schedule.loop2": "UNLOCALIZED: when completed",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 627",
"_": "Missing Localizations: 635",
"_": "->------------------------] 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.grace_period": "UNLOCALIZED: Grace Period",
"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.greater": "UNLOCALIZED: More than",
"create.schedule.condition.threshold.less": "UNLOCALIZED: Less than",
"create.schedule.condition.threshold.equal": "UNLOCALIZED: Exactly",
"create.schedule.condition.threshold.train_holds": "UNLOCALIZED: Train holds %1$s",
"create.schedule.condition.threshold.greater": "UNLOCALIZED: more than",
"create.schedule.condition.threshold.less": "UNLOCALIZED: less than",
"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.matching_content": "UNLOCALIZED: Matching Content",
"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.fluid_threshold": "UNLOCALIZED: Fluid 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.loop1": "UNLOCALIZED: Schedule starts over",
"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.logistics.item.LinkedControllerScreen;
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.CRecipes;
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(BlueprintScreen.class, new GhostIngredientHandler());
registration.addGhostIngredientHandler(LinkedControllerScreen.class, new GhostIngredientHandler());
registration.addGhostIngredientHandler(ScheduleScreen.class, new GhostIngredientHandler());
}
private class CategoryBuilder<T extends Recipe<?>> {

View file

@ -29,9 +29,12 @@ public class GhostIngredientHandler<T extends GhostItemContainer<?>>
if (ingredient instanceof ItemStack) {
for (int i = 36; i < gui.getMenu().slots.size(); i++) {
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)
break;
}
@ -41,8 +44,7 @@ public class GhostIngredientHandler<T extends GhostItemContainer<?>>
}
@Override
public void onComplete() {
}
public void onComplete() {}
@Override
public boolean shouldHighlightTargets() {

View file

@ -297,7 +297,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit
if (!initialized)
contraptionInitialize();
contraption.storage.entityTick(this);
contraption.tickStorage(this);
tickContraption();
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 {
private ContraptionInvWrapper inventory;
private ContraptionInvWrapper fuelInventory;
private CombinedTankWrapper fluidInventory;
private Map<BlockPos, MountedStorage> storage;
private Map<BlockPos, MountedFluidStorage> fluidStorage;
protected ContraptionInvWrapper inventory;
protected ContraptionInvWrapper fuelInventory;
protected CombinedTankWrapper fluidInventory;
protected Map<BlockPos, MountedStorage> storage;
protected Map<BlockPos, MountedFluidStorage> fluidStorage;
public MountedStorageManager() {
storage = new HashMap<>();
@ -48,27 +48,29 @@ public class MountedStorageManager {
public void createHandlers() {
Collection<MountedStorage> itemHandlers = storage.values();
inventory = wrap(itemHandlers.stream()
inventory = wrapItems(itemHandlers.stream()
.map(MountedStorage::getItemHandler)
.toList());
.toList(), false);
fuelInventory = wrap(itemHandlers.stream()
fuelInventory = wrapItems(itemHandlers.stream()
.filter(MountedStorage::canUseForFuel)
.map(MountedStorage::getItemHandler)
.toList());
.toList(), true);
List<IFluidHandler> fluidHandlers = fluidStorage.values()
fluidInventory = wrapFluids(fluidStorage.values()
.stream()
.map(MountedFluidStorage::getFluidHandler)
.collect(Collectors.toList());
fluidInventory = new CombinedTankWrapper(
Arrays.copyOf(fluidHandlers.toArray(), fluidHandlers.size(), IFluidHandler[].class));
.collect(Collectors.toList()));
}
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));
}
protected CombinedTankWrapper wrapFluids(Collection<IFluidHandler> list) {
return new CombinedTankWrapper(Arrays.copyOf(list.toArray(), list.size(), IFluidHandler[].class));
}
public void addBlock(BlockPos localPos, BlockEntity te) {
if (te != null && MountedStorage.canUseAsStorage(te))
storage.put(localPos, new MountedStorage(te));
@ -86,6 +88,26 @@ public class MountedStorageManager {
.put(NbtUtils.readBlockPos(c.getCompound("Pos")), MountedFluidStorage.deserialize(c.getCompound("Data"))));
if (clientPacket && presentTileEntities != null)
bindTanks(presentTileEntities);
List<IItemHandlerModifiable> handlers = new ArrayList<>();
List<IItemHandlerModifiable> fuelHandlers = new ArrayList<>();
for (MountedStorage mountedStorage : storage.values()) {
IItemHandlerModifiable itemHandler = mountedStorage.getItemHandler();
handlers.add(itemHandler);
if (mountedStorage.canUseForFuel())
fuelHandlers.add(itemHandler);
}
inventory = wrapItems(handlers, false);
fuelInventory = wrapItems(fuelHandlers, true);
fluidInventory = wrapFluids(fluidStorage.values()
.stream()
.map(MountedFluidStorage::getFluidHandler)
.toList());
}
public void bindTanks(Map<BlockPos, BlockEntity> presentTileEntities) {
fluidStorage.forEach((pos, mfs) -> {
BlockEntity tileEntity = presentTileEntities.get(pos);
if (!(tileEntity instanceof FluidTankTileEntity))
@ -98,24 +120,6 @@ public class MountedStorageManager {
.startWithValue(tank.getFillState());
mfs.assignTileEntity(tank);
});
List<IItemHandlerModifiable> handlers = new ArrayList<>();
List<IItemHandlerModifiable> fuelHandlers = new ArrayList<>();
for (MountedStorage mountedStorage : storage.values()) {
IItemHandlerModifiable itemHandler = mountedStorage.getItemHandler();
handlers.add(itemHandler);
if (mountedStorage.canUseForFuel())
fuelHandlers.add(itemHandler);
}
int index = 0;
IFluidHandler[] fluidHandlers = new IFluidHandler[fluidStorage.size()];
for (MountedFluidStorage mountedStorage : fluidStorage.values())
fluidHandlers[index++] = mountedStorage.getFluidHandler();
inventory = wrap(handlers);
fuelInventory = wrap(fuelHandlers);
fluidInventory = new CombinedTankWrapper(fluidHandlers);
}
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;
import org.apache.commons.lang3.tuple.Pair;
import com.simibubi.create.content.logistics.RedstoneLinkNetworkHandler.Frequency;
import com.simibubi.create.foundation.utility.Couple;
import net.minecraft.core.BlockPos;
@ -16,7 +15,7 @@ public interface IRedstoneLinkable {
public boolean isAlive();
public Pair<Frequency, Frequency> getNetworkKey();
public Couple<Frequency> getNetworkKey();
public BlockPos getLocation();

View file

@ -6,12 +6,12 @@ import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang3.tuple.Pair;
import java.util.concurrent.atomic.AtomicInteger;
import com.simibubi.create.Create;
import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.tileEntity.behaviour.linked.LinkBehaviour;
import com.simibubi.create.foundation.utility.Couple;
import com.simibubi.create.foundation.utility.WorldHelper;
import net.minecraft.nbt.CompoundTag;
@ -21,9 +21,11 @@ import net.minecraft.world.level.LevelAccessor;
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<>();
public final AtomicInteger globalPowerVersion = new AtomicInteger();
public static class Frequency {
public static final Frequency EMPTY = new Frequency(ItemStack.EMPTY);
private static final Map<Item, Frequency> simpleFrequencies = new IdentityHashMap<>();
@ -76,8 +78,8 @@ public class RedstoneLinkNetworkHandler {
}
public Set<IRedstoneLinkable> getNetworkOf(LevelAccessor world, IRedstoneLinkable actor) {
Map<Pair<Frequency, Frequency>, Set<IRedstoneLinkable>> networksInWorld = networksIn(world);
Pair<Frequency, Frequency> key = actor.getNetworkKey();
Map<Couple<Frequency>, Set<IRedstoneLinkable>> networksInWorld = networksIn(world);
Couple<Frequency> key = actor.getNetworkKey();
if (!networksInWorld.containsKey(key))
networksInWorld.put(key, new LinkedHashSet<>());
return networksInWorld.get(key);
@ -100,6 +102,7 @@ public class RedstoneLinkNetworkHandler {
public void updateNetworkOf(LevelAccessor world, IRedstoneLinkable actor) {
Set<IRedstoneLinkable> network = getNetworkOf(world, actor);
globalPowerVersion.incrementAndGet();
int power = 0;
for (Iterator<IRedstoneLinkable> iterator = network.iterator(); iterator.hasNext();) {
@ -141,7 +144,7 @@ public class RedstoneLinkNetworkHandler {
.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)) {
Create.LOGGER.warn("Tried to Access unprepared network space of " + WorldHelper.getDimensionID(world));
return new HashMap<>();
@ -149,4 +152,16 @@ public class RedstoneLinkNetworkHandler {
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;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.BiConsumer;
import com.google.common.collect.ImmutableList;
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.AllGuiTextures;
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.widget.IconButton;
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.networking.AllPackets;
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.client.gui.components.AbstractWidget;
import net.minecraft.client.gui.components.EditBox;
import net.minecraft.client.gui.components.events.GuiEventListener;
import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag;
@ -63,13 +57,13 @@ public class DisplayLinkScreen extends AbstractSimiScreen {
ScrollInput targetLineSelector;
Label targetLineLabel;
Couple<Set<Pair<AbstractWidget, String>>> configWidgets;
Couple<ModularGuiLine> configWidgets;
public DisplayLinkScreen(DisplayLinkTileEntity te) {
this.background = AllGuiTextures.DATA_GATHERER;
this.te = te;
sources = Collections.emptyList();
configWidgets = Couple.create(HashSet::new);
configWidgets = Couple.create(ModularGuiLine::new);
target = null;
}
@ -124,7 +118,7 @@ public class DisplayLinkScreen extends AbstractSimiScreen {
removeWidget(sourceTypeSelector);
removeWidget(sourceTypeLabel);
configWidgets.forEach(s -> s.forEach(p -> removeWidget(p.getFirst())));
configWidgets.forEach(s -> s.forEach(this::removeWidget));
targetLineSelector = null;
sourceTypeSelector = null;
@ -185,93 +179,15 @@ public class DisplayLinkScreen extends AbstractSimiScreen {
: Lang.translate("display_link.display_on_multiline"));
configWidgets.forEach(s -> {
s.forEach(p -> removeWidget(p.getFirst()));
s.forEach(this::removeWidget);
s.clear();
});
DisplayLinkContext context = new DisplayLinkContext(minecraft.level, te);
configWidgets.forEachWithContext((s, first) -> source.initConfigurationWidgets(context,
new LineBuilder(s, guiLeft + 60, guiTop + (first ? 51 : 72)), first));
configWidgets.forEach(s -> s.forEach(p -> {
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));
new ModularGuiLineBuilder(font, s, guiLeft + 60, guiTop + (first ? 51 : 72)), first));
configWidgets
.forEach(s -> s.loadValues(te.getSourceConfig(), this::addRenderableWidget, this::addRenderableOnly));
}
@Override
@ -282,7 +198,7 @@ public class DisplayLinkScreen extends AbstractSimiScreen {
if (!sources.isEmpty()) {
sourceData.putString("Id",
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,
@ -310,12 +226,14 @@ public class DisplayLinkScreen extends AbstractSimiScreen {
minecraft.getItemRenderer()
.renderGuiItem(targetIcon, x + 37, y + 105);
configWidgets.forEachWithContext((s, first) -> s.forEach(p -> {
if (p.getSecond()
.equals("Dummy"))
return;
renderWidgetBG(ms, p.getFirst(), first);
}));
ms.pushPose();
ms.translate(0, guiTop + 48, 0);
configWidgets.getFirst()
.renderWidgetBG(guiLeft, ms);
ms.translate(0, 21, 0);
configWidgets.getSecond()
.renderWidgetBG(guiLeft, ms);
ms.popPose();
ms.pushPose();
TransformStack.cast(ms)
@ -330,21 +248,6 @@ public class DisplayLinkScreen extends AbstractSimiScreen {
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
protected void renderWindowForeground(PoseStack ms, int mouseX, int mouseY, float 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.simibubi.create.content.logistics.block.display.DisplayBehaviour;
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.DisplayTarget;
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.FlapDisplayTileEntity;
import com.simibubi.create.foundation.gui.ModularGuiLineBuilder;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent;
@ -70,6 +70,6 @@ public abstract class DisplaySource extends DisplayBehaviour {
}
@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 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.redstone.StockpileSwitchTileEntity;
import com.simibubi.create.content.logistics.trains.management.display.FlapDisplaySection;
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 net.minecraft.network.chat.MutableComponent;
@ -83,7 +83,7 @@ public class FillLevelDisplaySource extends NumericSingleLineDisplaySource {
@Override
@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);
if (isFirstLine)
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.logistics.block.display.DisplayLinkBlock;
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.target.DisplayTargetStats;
import com.simibubi.create.foundation.gui.ModularGuiLineBuilder;
import com.simibubi.create.foundation.utility.Lang;
import net.minecraft.nbt.CompoundTag;
@ -101,7 +101,7 @@ public class ItemThoughputDisplaySource extends AccumulatedItemCountDisplaySourc
@Override
@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);
if (isFirstLine)
return;

View file

@ -4,7 +4,7 @@ import java.util.stream.Stream;
import com.google.common.collect.ImmutableList;
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.Lang;
@ -56,7 +56,7 @@ public class ScoreboardDisplaySource extends ValueListDisplaySource {
}
@Override
public void initConfigurationWidgets(DisplayLinkContext context, LineBuilder builder, boolean isFirstLine) {
public void initConfigurationWidgets(DisplayLinkContext context, ModularGuiLineBuilder builder, boolean isFirstLine) {
if (isFirstLine)
builder.addTextInput(0, 137, (e, t) -> {
e.setValue("");

View file

@ -4,11 +4,11 @@ import java.util.List;
import com.google.common.collect.ImmutableList;
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.trains.management.display.FlapDisplayLayout;
import com.simibubi.create.content.logistics.trains.management.display.FlapDisplaySection;
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 net.minecraft.ChatFormatting;
@ -25,13 +25,13 @@ public abstract class SingleLineDisplaySource extends DisplaySource {
@Override
@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))
addLabelingTextBox(builder);
}
@OnlyIn(Dist.CLIENT)
protected void addLabelingTextBox(LineBuilder builder) {
protected void addLabelingTextBox(ModularGuiLineBuilder builder) {
builder.addTextInput(0, 137, (e, t) -> {
e.setValue("");
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 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 net.minecraft.network.chat.Component;
@ -58,6 +58,6 @@ public abstract class StatTrackingDisplaySource extends ScoreboardDisplaySource
@Override
@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.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.trains.management.display.FlapDisplayLayout;
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.edgePoint.station.GlobalStation;
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 net.minecraft.ChatFormatting;
@ -171,7 +171,7 @@ public class StationSummaryDisplaySource extends DisplaySource {
@Override
@OnlyIn(Dist.CLIENT)
public void initConfigurationWidgets(DisplayLinkContext context, LineBuilder builder, boolean isFirstLine) {
public void initConfigurationWidgets(DisplayLinkContext context, ModularGuiLineBuilder builder, boolean isFirstLine) {
if (isFirstLine) {
builder.addTextInput(0, 137, (e, t) -> {
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.content.contraptions.components.clock.CuckooClockTileEntity;
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.trains.management.display.FlapDisplaySection;
import com.simibubi.create.foundation.gui.ModularGuiLineBuilder;
import com.simibubi.create.foundation.utility.Lang;
import net.minecraft.network.chat.MutableComponent;
@ -72,7 +72,7 @@ public class TimeOfDayDisplaySource extends SingleLineDisplaySource {
@Override
@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);
if (isFirstLine)
return;

View file

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

View file

@ -1,8 +1,5 @@
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.behaviour.linked.LinkBehaviour;
@ -46,15 +43,12 @@ public class LinkedControllerBindPacket extends LinkedControllerPacketBase {
if (linkBehaviour == null)
return;
Pair<Frequency, Frequency> pair = linkBehaviour.getNetworkKey();
frequencyItems.setStackInSlot(button * 2, pair.getKey()
.getStack()
.copy());
frequencyItems.setStackInSlot(button * 2 + 1, pair.getValue()
.getStack()
.copy());
linkBehaviour.getNetworkKey()
.forEachWithContext((f, first) -> frequencyItems.setStackInSlot(button * 2 + (first ? 0 : 1), f.getStack()
.copy()));
heldItem.getTag().put("Items", frequencyItems.serializeNBT());
heldItem.getTag()
.put("Items", frequencyItems.serializeNBT());
}
@Override

View file

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

View file

@ -19,8 +19,8 @@ import javax.annotation.Nullable;
import org.apache.commons.lang3.mutable.MutableDouble;
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.train.TrainCargoManager;
import com.simibubi.create.content.logistics.trains.DimensionPalette;
import com.simibubi.create.content.logistics.trains.TrackGraph;
import com.simibubi.create.content.logistics.trains.TrackNodeLocation;
@ -59,7 +59,7 @@ public class Carriage {
public int bogeySpacing;
public Couple<CarriageBogey> bogeys;
public MountedStorageManager storage;
public TrainCargoManager storage;
CompoundTag serialisedEntity;
Map<Integer, CompoundTag> serialisedPassengers;
@ -76,7 +76,7 @@ public class Carriage {
this.presentConductors = Couple.create(false, false);
this.serialisedPassengers = new HashMap<>();
this.entities = new HashMap<>();
this.storage = new MountedStorageManager();
this.storage = new TrainCargoManager();
bogey1.setLeading();
bogey1.carriage = this;

View file

@ -11,6 +11,7 @@ import java.util.Optional;
import org.apache.commons.lang3.tuple.Pair;
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.Contraption;
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.interaction.controls.ControlsBlock;
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.HeatLevel;
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.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.items.IItemHandlerModifiable;
@ -74,6 +77,7 @@ public class CarriageContraption extends Contraption {
soundQueue = new ArrivalSoundQueue();
portalCutoffMin = Integer.MIN_VALUE;
portalCutoffMax = Integer.MAX_VALUE;
storage = new TrainCargoManager();
}
public void setSoundQueueOffset(int offset) {
@ -127,7 +131,7 @@ public class CarriageContraption extends Contraption {
// carriage manages it instead
Carriage carriage = cce.getCarriage();
if (carriage.storage == null) {
carriage.storage = storage;
carriage.storage = (TrainCargoManager) storage;
storage = new MountedStorageManager();
}
storageProxy = carriage.storage;
@ -325,5 +329,16 @@ public class CarriageContraption extends Contraption {
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

@ -186,6 +186,8 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
dimensional.pivot = null;
carriage.updateContraptionAnchors();
dimensional.updateRenderedCutoff();
carriage.storage.bindTanks(contraption.presentTileEntities);
}
updateTrackGraph();
} else

View file

@ -170,6 +170,9 @@ public class Train {
return;
}
if (heldForAssembly && getCurrentStation() == null)
heldForAssembly = false;
updateConductors();
runtime.tick(level);
navigation.tick(level);

View file

@ -1,15 +1,15 @@
package com.simibubi.create.content.logistics.trains.management.schedule;
import java.util.List;
import java.util.function.BiConsumer;
import javax.annotation.Nullable;
import com.google.common.collect.ImmutableList;
import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.foundation.gui.ModularGuiLineBuilder;
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.TranslatableComponent;
import net.minecraft.resources.ResourceLocation;
@ -23,31 +23,36 @@ public interface IScheduleInput {
public abstract ResourceLocation getId();
public default boolean needsSlot() {
return false;
}
public abstract CompoundTag getData();
@OnlyIn(Dist.CLIENT)
public default void createWidgets(ScheduleScreen screen,
List<Pair<GuiEventListener, BiConsumer<IScheduleInput, GuiEventListener>>> editorSubWidgets,
List<Integer> dividers, int x, int y) {}
public default int slotsTargeted() {
return 0;
}
public default List<Component> getTitleAs(String type) {
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() {
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
public default List<Component> getSecondLineTooltip() {
public default List<Component> getSecondLineTooltip(int slot) {
return null;
}
@OnlyIn(Dist.CLIENT)
public default void initConfigurationWidgets(ModularGuiLineBuilder builder) {};
@OnlyIn(Dist.CLIENT)
public default boolean renderSpecialIcon(PoseStack ms, int x, int y) {
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.IdleCargoCondition;
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.ScheduledDelay;
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("fluid_threshold", FluidThresholdCondition::new);
registerCondition("item_threshold", ItemThresholdCondition::new);
registerCondition("redstone_link", RedstoneLinkCondition::new);
registerCondition("idle", IdleCargoCondition::new);
registerCondition("unloaded", StationUnloadedCondition::new);
registerCondition("powered", StationPoweredCondition::new);

View file

@ -17,7 +17,9 @@ import net.minecraftforge.items.SlotItemHandler;
public class ScheduleContainer extends GhostItemContainer<ItemStack> {
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) {
super(type, id, inv, extraData);
@ -29,7 +31,7 @@ public class ScheduleContainer extends GhostItemContainer<ItemStack> {
@Override
protected ItemStackHandler createGhostInventory() {
return new ItemStackHandler(1);
return new ItemStackHandler(slots);
}
@Override
@ -51,7 +53,8 @@ public class ScheduleContainer extends GhostItemContainer<ItemStack> {
@Override
protected void addSlots() {
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
@ -86,13 +89,17 @@ public class ScheduleContainer extends GhostItemContainer<ItemStack> {
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);
this.targetIndex = targetIndex;
}
@Override
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 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.management.display.GlobalTrainDisplayData.TrainDeparturePrediction;
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.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.DestinationInstruction;
import com.simibubi.create.content.logistics.trains.management.schedule.destination.ScheduleInstruction;
@ -57,6 +58,8 @@ public class ScheduleRuntime {
return;
state = State.POST_TRANSIT;
conditionProgress.clear();
for (Carriage carriage : train.carriages)
carriage.storage.resetIdleCargoTracker();
if (ticksInTransit > 0) {
int current = predictionTicks.get(currentEntry);
@ -143,6 +146,9 @@ public class ScheduleRuntime {
conditionProgress.set(i, progress + 1);
}
}
for (Carriage carriage : train.carriages)
carriage.storage.tickIdleCargoTracker();
}
public GlobalStation startCurrentInstruction() {
@ -322,8 +328,8 @@ public class ScheduleRuntime {
ScheduleEntry scheduleEntry = schedule.entries.get(index);
for (List<ScheduleWaitCondition> list : scheduleEntry.conditions)
for (ScheduleWaitCondition condition : list)
if (condition instanceof TimedWaitCondition wait)
return wait.timeUnit.ticksPer * wait.value;
if (condition instanceof ScheduledDelay wait)
return wait.totalWaitTicks();
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.Optional;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
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.schedule.condition.ScheduleWaitCondition;
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.ScheduleInstruction;
import com.simibubi.create.foundation.gui.AllGuiTextures;
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.container.AbstractSimiContainerScreen;
import com.simibubi.create.foundation.gui.container.GhostItemSubmitPacket;
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.Indicator;
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.components.EditBox;
import net.minecraft.client.gui.components.Widget;
import net.minecraft.client.gui.components.events.GuiEventListener;
import net.minecraft.client.renderer.Rect2i;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
@ -90,9 +89,8 @@ public class ScheduleScreen extends AbstractSimiContainerScreen<ScheduleContaine
private SelectionScrollInput scrollInput;
private Label scrollInputLabel;
private IconButton editorConfirm, editorDelete;
private ModularGuiLine editorSubWidgets;
private Consumer<Boolean> onEditorClose;
private List<Pair<GuiEventListener, BiConsumer<IScheduleInput, GuiEventListener>>> editorSubWidgets;
private List<Integer> editorDividers;
private DestinationSuggestions destinationSuggestions;
@ -104,7 +102,7 @@ public class ScheduleScreen extends AbstractSimiContainerScreen<ScheduleContaine
if (!tag.isEmpty())
schedule = Schedule.fromTag(tag);
container.slotsActive = false;
editorSubWidgets = new ArrayList<>();
editorSubWidgets = new ModularGuiLine();
}
@Override
@ -178,7 +176,13 @@ public class ScheduleScreen extends AbstractSimiContainerScreen<ScheduleContaine
if (allowDeletion)
editorDelete = new IconButton(leftPos + 56 - 45, topPos + 65 + 22, AllIcons.I_TRASH);
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) {
int startIndex = 0;
@ -260,15 +264,15 @@ public class ScheduleScreen extends AbstractSimiContainerScreen<ScheduleContaine
removeWidget(editorDelete);
IScheduleInput editing = editingCondition == null ? editingDestination : editingCondition;
editing.setItem(menu.getSlot(36)
.getItem());
for (int i = 0; i < editing.slotsTargeted(); i++) {
editing.setItem(i, menu.ghostInventory.getStackInSlot(i));
AllPackets.channel.sendToServer(new GhostItemSubmitPacket(ItemStack.EMPTY, i));
}
editorSubWidgets.forEach(p -> p.getSecond()
.accept(editing, p.getFirst()));
editorSubWidgets.forEach(p -> removeWidget(p.getFirst()));
editorSubWidgets.saveValues(editing.getData());
editorSubWidgets.forEach(this::removeWidget);
editorSubWidgets.clear();
editorDividers = null;
editingCondition = null;
editingDestination = null;
editorConfirm = null;
@ -279,32 +283,25 @@ public class ScheduleScreen extends AbstractSimiContainerScreen<ScheduleContaine
protected void updateEditorSubwidgets(IScheduleInput field) {
destinationSuggestions = null;
menu.targetSlotActive = field.needsSlot();
editorSubWidgets.forEach(p -> removeWidget(p.getFirst()));
menu.targetSlotsActive = field.slotsTargeted();
editorSubWidgets.forEach(this::removeWidget);
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())
editorDividers = null;
if (field instanceof DestinationInstruction) {
EditBox destinationBox = (EditBox) editorSubWidgets.get(0)
.getFirst();
editorSubWidgets.forEach(e -> {
if (!(e instanceof EditBox destinationBox))
return;
destinationSuggestions = new DestinationSuggestions(this.minecraft, this, destinationBox, this.font,
getViableStations(field), topPos + 33);
destinationSuggestions.setAllowSuggestions(true);
destinationSuggestions.updateCommandInfo();
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<>();
initialConditions.add(delay);
entry.instruction = editingDestination;
delay.value = 5;
delay.timeUnit = TimeUnit.SECONDS;
entry.conditions.add(initialConditions);
schedule.entries.add(entry);
}, true);
@ -1005,17 +1000,22 @@ public class ScheduleScreen extends AbstractSimiContainerScreen<ScheduleContaine
if (editingCondition == null && editingDestination == null)
return;
int x = leftPos + 53;
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;
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++) {
List<Component> secondLineTooltip = rendered.getSecondLineTooltip(i);
if (secondLineTooltip == null || (hoveredSlot != menu.getSlot(36 + i) || !hoveredSlot.getItem()
.isEmpty()))
return;
continue;
renderTooltip(matrixStack, secondLineTooltip, Optional.empty(), mouseX, mouseY);
}
}
@Override
protected void renderBg(PoseStack pPoseStack, float pPartialTick, int pMouseX, int pMouseY) {
@ -1042,7 +1042,11 @@ public class ScheduleScreen extends AbstractSimiContainerScreen<ScheduleContaine
(float) topPos + 44, 0x505050);
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();
ItemStack icon = summary.getFirst();
if (icon.isEmpty())
@ -1055,12 +1059,10 @@ public class ScheduleScreen extends AbstractSimiContainerScreen<ScheduleContaine
.render(pPoseStack);
}
if (editorDividers == null)
return;
AllGuiTextures.SCHEDULE_EDITOR_SECOND_LINE.render(pPoseStack, leftPos + 74, topPos + 87);
for (Integer integer : editorDividers)
AllGuiTextures.SCHEDULE_EDITOR_DIVIDER.render(pPoseStack, leftPos + 74 + integer, topPos + 87);
pPoseStack.pushPose();
pPoseStack.translate(0, getGuiTop() + 87, 0);
editorSubWidgets.renderWidgetBG(getGuiLeft() + 77, pPoseStack);
pPoseStack.popPose();
}
@Override

View file

@ -2,29 +2,25 @@ package com.simibubi.create.content.logistics.trains.management.schedule.conditi
import java.util.Arrays;
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.gui.widget.Label;
import com.simibubi.create.foundation.gui.widget.ScrollInput;
import com.simibubi.create.foundation.gui.widget.SelectionScrollInput;
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.gui.ModularGuiLineBuilder;
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.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.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
public abstract class CargoThresholdCondition extends ScheduleWaitCondition {
public abstract class CargoThresholdCondition extends LazyTickedScheduleCondition {
public static enum Ops {
GREATER(">"), LESS("<"), EQUAL("=");
@ -34,6 +30,15 @@ public abstract class CargoThresholdCondition extends ScheduleWaitCondition {
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() {
return Arrays.stream(values())
.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 int threshold;
public CargoThresholdCondition() {
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();
@ -50,28 +71,33 @@ public abstract class CargoThresholdCondition extends ScheduleWaitCondition {
@Override
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
protected void write(CompoundTag tag) {
NBTHelper.writeEnum(tag, "Operator", ops);
tag.putInt("Threshold", threshold);
public int slotsTargeted() {
return 1;
}
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
protected void read(CompoundTag tag) {
ops = NBTHelper.readEnum(tag, "Operator", CargoThresholdCondition.Ops.class);
threshold = tag.getInt("Threshold");
}
@Override
public boolean needsSlot() {
return true;
}
@Override
public List<Component> getSecondLineTooltip() {
public List<Component> getSecondLineTooltip(int slot) {
return ImmutableList.of(Lang.translate("schedule.condition.threshold.place_item"),
Lang.translate("schedule.condition.threshold.place_item_2")
.withStyle(ChatFormatting.GRAY));
@ -79,53 +105,14 @@ public abstract class CargoThresholdCondition extends ScheduleWaitCondition {
@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 + 109, y + 52, 35, 10, new TextComponent(threshold + ""));
editBox.setBordered(false);
editBox.setValue(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())
public void initConfigurationWidgets(ModularGuiLineBuilder builder) {
builder.addSelectionScrollInput(0, 24, (i, l) -> {
i.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);
.format(state -> new TextComponent(" " + Ops.values()[state].formatted));
}, "Operator");
builder.addIntegerTextInput(29, 41, (e, t) -> {
}, "Threshold");
}
}

View file

@ -1,30 +1,28 @@
package com.simibubi.create.content.logistics.trains.management.schedule.condition;
import java.util.List;
import java.util.function.BiConsumer;
import com.google.common.collect.ImmutableList;
import com.simibubi.create.Create;
import com.simibubi.create.content.contraptions.processing.EmptyingByBasin;
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.management.schedule.ScheduleScreen;
import com.simibubi.create.foundation.gui.widget.Label;
import com.simibubi.create.content.logistics.trains.entity.Carriage;
import com.simibubi.create.content.logistics.trains.entity.Train;
import com.simibubi.create.foundation.gui.ModularGuiLineBuilder;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.Pair;
import net.minecraft.ChatFormatting;
import net.minecraft.client.Minecraft;
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.minecraft.network.chat.TranslatableComponent;
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;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.IFluidHandler;
public class FluidThresholdCondition extends CargoThresholdCondition {
public ItemStack compareStack = ItemStack.EMPTY;
@ -41,17 +39,46 @@ public class FluidThresholdCondition extends CargoThresholdCondition {
}
@Override
protected void write(CompoundTag tag) {
super.write(tag);
protected boolean test(Level level, Train train) {
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());
}
@Override
protected void read(CompoundTag tag) {
super.read(tag);
protected void readAdditional(CompoundTag tag) {
super.readAdditional(tag);
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)
private FluidStack loadFluid() {
if (fluidStack != null)
@ -70,8 +97,8 @@ public class FluidThresholdCondition extends CargoThresholdCondition {
public List<Component> getTitleAs(String type) {
return ImmutableList.of(
Lang.translate("schedule.condition.threshold.train_holds",
Lang.translate("schedule.condition.threshold." + Lang.asId(ops.name()))),
Lang.translate("schedule.condition.threshold.x_units_of_item", threshold,
Lang.translate("schedule.condition.threshold." + Lang.asId(getOperator().name()))),
Lang.translate("schedule.condition.threshold.x_units_of_item", getThreshold(),
Lang.translate("schedule.condition.threshold.buckets"),
compareStack.getItem() instanceof FilterItem
? Lang.translate("schedule.condition.threshold.matching_content")
@ -80,10 +107,15 @@ public class FluidThresholdCondition extends CargoThresholdCondition {
}
@Override
public void setItem(ItemStack stack) {
public void setItem(int slot, ItemStack stack) {
compareStack = stack;
}
@Override
public ItemStack getItem(int slot) {
return compareStack;
}
@Override
public ResourceLocation getId() {
return Create.asResource("fluid_threshold");
@ -91,15 +123,12 @@ public class FluidThresholdCondition extends CargoThresholdCondition {
@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);
public void initConfigurationWidgets(ModularGuiLineBuilder builder) {
super.initConfigurationWidgets(builder);
builder.addSelectionScrollInput(71, 50, (i, l) -> {
i.forOptions(ImmutableList.of(Lang.translate("schedule.condition.threshold.buckets")))
.titled(null);
}, "Measure");
}
TranslatableComponent buckets = Lang.translate("schedule.condition.threshold.buckets");
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;
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.Pair;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
public class IdleCargoCondition extends TimedWaitCondition {
@Override
public Pair<ItemStack, Component> getSummary() {
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() {
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;
import java.util.List;
import java.util.function.BiConsumer;
import com.google.common.collect.ImmutableList;
import com.simibubi.create.Create;
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.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.content.logistics.trains.entity.Carriage;
import com.simibubi.create.content.logistics.trains.entity.Train;
import com.simibubi.create.foundation.gui.ModularGuiLineBuilder;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.Pair;
import net.minecraft.ChatFormatting;
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.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;
import net.minecraftforge.items.IItemHandlerModifiable;
public class ItemThresholdCondition extends CargoThresholdCondition {
public ItemStack stack = ItemStack.EMPTY;
public boolean stacks;
@Override
protected Component getUnit() {
return new TextComponent(stacks ? "\u25A4" : "");
return new TextComponent(inStacks() ? "\u25A4" : "");
}
@Override
@ -39,36 +35,78 @@ public class ItemThresholdCondition extends CargoThresholdCondition {
}
@Override
protected void write(CompoundTag tag) {
super.write(tag);
protected boolean test(Level level, Train train) {
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.putBoolean("Stacks", stacks);
}
@Override
protected void read(CompoundTag tag) {
super.read(tag);
protected void readAdditional(CompoundTag tag) {
super.readAdditional(tag);
stack = ItemStack.of(tag.getCompound("Item"));
stacks = tag.getBoolean("Stacks");
}
@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;
}
@Override
public ItemStack getItem(int slot) {
return stack;
}
@Override
public List<Component> getTitleAs(String type) {
return ImmutableList.of(
Lang.translate("schedule.condition.threshold.train_holds",
Lang.translate("schedule.condition.threshold." + Lang.asId(ops.name()))),
Lang.translate("schedule.condition.threshold.x_units_of_item", threshold,
Lang.translate("schedule.condition.threshold." + (stacks ? "stacks" : "items")),
Lang.translate("schedule.condition.threshold." + Lang.asId(getOperator().name()))),
Lang.translate("schedule.condition.threshold.x_units_of_item", getThreshold(),
Lang.translate("schedule.condition.threshold." + (inStacks() ? "stacks" : "items")),
stack.getItem() instanceof FilterItem ? Lang.translate("schedule.condition.threshold.matching_content")
: stack.getHoverName())
.withStyle(ChatFormatting.DARK_AQUA));
}
private boolean inStacks() {
return intData("Measure") == 1;
}
@Override
public ResourceLocation getId() {
return Create.asResource("item_threshold");
@ -76,24 +114,12 @@ public class ItemThresholdCondition extends CargoThresholdCondition {
@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);
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"),
public void initConfigurationWidgets(ModularGuiLineBuilder builder) {
super.initConfigurationWidgets(builder);
builder.addSelectionScrollInput(71, 50, (i, l) -> {
i.forOptions(ImmutableList.of(Lang.translate("schedule.condition.threshold.items"),
Lang.translate("schedule.condition.threshold.stacks")))
.titled(Lang.translate("schedule.condition.threshold.item_measure"))
.writingTo(label)
.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) -> {
}));
.titled(Lang.translate("schedule.condition.threshold.item_measure"));
}, "Measure");
}
}

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.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.ScheduleDataEntry;
import com.simibubi.create.foundation.utility.Pair;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.Level;
public abstract class ScheduleWaitCondition implements IScheduleInput {
public abstract class ScheduleWaitCondition extends ScheduleDataEntry {
protected abstract void write(CompoundTag tag);
protected abstract void read(CompoundTag tag);
public boolean tickCompletion(Level level, Train train, CompoundTag context) {
return false; // TODO: make abstract
}
public abstract boolean tickCompletion(Level level, Train train, CompoundTag context);
public final CompoundTag write() {
CompoundTag tag = new CompoundTag();
tag.putString("Id", getId().toString());
write(tag);
tag.put("Data", data.copy());
writeAdditional(tag);
return tag;
}
@ -43,7 +38,8 @@ public abstract class ScheduleWaitCondition implements IScheduleInput {
}
ScheduleWaitCondition condition = supplier.get();
condition.read(tag);
condition.data = tag.getCompound("Data");
condition.readAdditional(tag);
return condition;
}

View file

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

View file

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

View file

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

View file

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

View file

@ -1,22 +1,12 @@
package com.simibubi.create.content.logistics.trains.management.schedule.condition;
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.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.ModularGuiLineBuilder;
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.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.minecraft.network.chat.TranslatableComponent;
@ -26,8 +16,6 @@ import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
public abstract class TimedWaitCondition extends ScheduleWaitCondition {
public TimedWaitCondition.TimeUnit timeUnit = TimeUnit.TICKS;
public int value;
public static enum TimeUnit {
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) {
if (compact)
return new TextComponent(value + timeUnit.suffix);
return new TextComponent(value + " ").append(Lang.translate(timeUnit.key));
return new TextComponent(getValue() + getUnit().suffix);
return new TextComponent(getValue() + " ").append(Lang.translate(getUnit().key));
}
@Override
@ -63,73 +60,39 @@ public abstract class TimedWaitCondition extends ScheduleWaitCondition {
.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
public ItemStack getSecondLineIcon() {
return new ItemStack(Items.REPEATER);
}
@Override
public List<Component> getSecondLineTooltip() {
public List<Component> getSecondLineTooltip(int slot) {
return ImmutableList.of(Lang.translate("generic.duration"));
}
public int getValue() {
return intData("Value");
}
public TimeUnit getUnit() {
return enumData("TimeUnit", TimeUnit.class);
}
@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);
public void initConfigurationWidgets(ModularGuiLineBuilder builder) {
builder.addScrollInput(0, 31, (i, l) -> {
i.titled(Lang.translate("generic.duration"))
.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 + ""));
editBox.setBordered(false);
editBox.setValue(value + "");
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;
builder.addSelectionScrollInput(36, 85, (i, l) -> {
i.forOptions(TimeUnit.translatedOptions())
.titled(Lang.translate("generic.timeUnit"));
}, "TimeUnit");
}
});
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.Items;
public class ChangeTitleInstruction extends ScheduleInstructionWithEditBox {
public class ChangeTitleInstruction extends TextScheduleInstruction {
@Override
public Pair<ItemStack, Component> getSummary() {
@ -45,7 +45,7 @@ public class ChangeTitleInstruction extends ScheduleInstructionWithEditBox {
}
@Override
public List<Component> getSecondLineTooltip() {
public List<Component> getSecondLineTooltip(int slot) {
return ImmutableList.of(Lang.translate("schedule.instruction.name_edit_box"),
Lang.translate("schedule.instruction.name_edit_box_1")
.withStyle(ChatFormatting.GRAY),

View file

@ -12,7 +12,6 @@ import com.simibubi.create.foundation.utility.Pair;
import net.minecraft.ChatFormatting;
import net.minecraft.client.gui.components.EditBox;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent;
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.OnlyIn;
public class DestinationInstruction extends ScheduleInstructionWithEditBox {
public boolean isWaypoint;
public class DestinationInstruction extends TextScheduleInstruction {
@Override
public Pair<ItemStack, Component> getSummary() {
@ -31,19 +28,7 @@ public class DestinationInstruction extends ScheduleInstructionWithEditBox {
@Override
public boolean supportsConditions() {
return !isWaypoint;
}
@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);
return true;
}
@Override
@ -61,7 +46,7 @@ public class DestinationInstruction extends ScheduleInstructionWithEditBox {
}
@Override
public List<Component> getSecondLineTooltip() {
public List<Component> getSecondLineTooltip(int slot) {
return ImmutableList.of(Lang.translate("schedule.instruction.filter_edit_box"),
Lang.translate("schedule.instruction.filter_edit_box_1")
.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 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.ScheduleDataEntry;
import com.simibubi.create.foundation.utility.Pair;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceLocation;
public abstract class ScheduleInstruction implements IScheduleInput {
protected abstract void write(CompoundTag tag);
protected abstract void read(CompoundTag tag);
public abstract class ScheduleInstruction extends ScheduleDataEntry {
public abstract boolean supportsConditions();
public final CompoundTag write() {
CompoundTag tag = new CompoundTag();
tag.putString("Id", getId().toString());
write(tag);
tag.put("Data", data.copy());
writeAdditional(tag);
return tag;
}
@ -39,7 +36,8 @@ public abstract class ScheduleInstruction implements IScheduleInput {
}
ScheduleInstruction scheduleDestination = supplier.get();
scheduleDestination.read(tag);
scheduleDestination.data = tag.getCompound("Data");
scheduleDestination.readAdditional(tag);
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.SmartTileEntity;
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
import com.simibubi.create.foundation.utility.Debug;
import com.simibubi.create.foundation.utility.Pair;
import net.minecraft.core.BlockPos;
@ -87,8 +86,6 @@ public class TrackTileEntity extends SmartTileEntity implements ITransformableTE
Vec3 bcEndAxis = bc.axes.getSecond();
if (v.distanceTo(bcEndAxis) < 1 / 1024f || v.distanceTo(bcEndAxis.scale(-1)) < 1 / 1024f)
level.setBlock(key, blockState.setValue(TrackBlock.HAS_TE, true), 3);
else
Debug.debugChat(v + " != " + bcEndAxis);
}
BlockEntity blockEntity = level.getBlockEntity(key);

View file

@ -128,8 +128,7 @@ public abstract class AbstractSimiScreen extends Screen {
return false;
}
protected void prepareFrame() {
}
protected void prepareFrame() {}
protected void renderWindowBackground(PoseStack ms, int mouseX, int mouseY, float partialTicks) {
renderBackground(ms);
@ -141,16 +140,16 @@ public abstract class AbstractSimiScreen extends Screen {
for (Widget widget : renderables) {
if (widget instanceof AbstractSimiWidget simiWidget && simiWidget.isHoveredOrFocused()) {
List<Component> tooltip = simiWidget.getToolTip();
int ttx = simiWidget.lockedTooltipX;
int tty = simiWidget.lockedTooltipY;
if (!tooltip.isEmpty())
renderComponentTooltip(ms, tooltip, ttx == -1 ? mouseX : ttx, tty == -1 ? mouseY : tty);
if (tooltip.isEmpty())
continue;
int ttx = simiWidget.lockedTooltipX == -1 ? mouseX : simiWidget.lockedTooltipX + simiWidget.x;
int tty = simiWidget.lockedTooltipY == -1 ? mouseY : simiWidget.lockedTooltipY + simiWidget.y;
renderComponentTooltip(ms, tooltip, ttx, tty);
}
}
}
protected void endFrame() {
}
protected void endFrame() {}
@Deprecated
protected void debugWindowArea(PoseStack matrixStack) {

View file

@ -83,6 +83,7 @@ public enum AllGuiTextures implements ScreenElement {
DATA_GATHERER("display_link", 235, 162),
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_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_ACTION("schedule", 209, 239, 11, 16),
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_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_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
}
protected void renderForeground(PoseStack matrixStack, int mouseX, int mouseY, float partialTicks) {
renderTooltip(matrixStack, mouseX, mouseY);
protected void renderForeground(PoseStack ms, int mouseX, int mouseY, float partialTicks) {
renderTooltip(ms, mouseX, mouseY);
for (Widget widget : renderables) {
if (widget instanceof AbstractSimiWidget simiWidget && simiWidget.isHoveredOrFocused()) {
List<Component> tooltip = simiWidget.getToolTip();
int ttx = simiWidget.lockedTooltipX;
int tty = simiWidget.lockedTooltipY;
if (!tooltip.isEmpty())
renderComponentTooltip(matrixStack, tooltip, ttx == -1 ? mouseX : ttx, tty == -1 ? mouseY : tty);
if (tooltip.isEmpty())
continue;
int ttx = simiWidget.lockedTooltipX == -1 ? mouseX : simiWidget.lockedTooltipX + simiWidget.x;
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 Label displayLabel;
protected boolean inverted;
protected Function<Integer, Component> formatter;
protected int min, max;
protected int shiftStep;
@ -33,6 +34,7 @@ public class ScrollInput extends AbstractSimiWidget {
max = 1;
shiftStep = 5;
step = standardStep();
formatter = i -> new TextComponent(String.valueOf(i));
}
public Function<StepContext, Integer> standardStep() {
@ -55,6 +57,11 @@ public class ScrollInput extends AbstractSimiWidget {
return this;
}
public ScrollInput format(Function<Integer, Component> formatter) {
this.formatter = formatter;
return this;
}
public ScrollInput removeCallback() {
this.onScroll = null;
return this;
@ -73,6 +80,7 @@ public class ScrollInput extends AbstractSimiWidget {
public ScrollInput writingTo(Label label) {
this.displayLabel = label;
if (label != null)
writeToLabel();
return this;
}
@ -138,14 +146,19 @@ public class ScrollInput extends AbstractSimiWidget {
}
protected void writeToLabel() {
displayLabel.text = new TextComponent(String.valueOf(state));
displayLabel.text = formatter.apply(state);
}
protected void updateTooltip() {
toolTip.clear();
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));
if (title == null)
return;
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) {
this.options = options;
this.max = options.size();
format(options::get);
updateTooltip();
return this;
}
@Override
protected void writeToLabel() {
displayLabel.text = options.get(state);
}
@Override
protected void updateTooltip() {
toolTip.clear();
if (title == null)
return;
toolTip.add(title.plainCopy()
.withStyle(s -> s.withColor(HEADER_RGB)));
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.behaviour.BehaviourType;
import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform;
import com.simibubi.create.foundation.utility.Couple;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
@ -109,8 +110,8 @@ public class LinkBehaviour extends TileEntityBehaviour implements IRedstoneLinka
}
@Override
public Pair<Frequency, Frequency> getNetworkKey() {
return Pair.of(frequencyFirst, frequencyLast);
public Couple<Frequency> getNetworkKey() {
return Couple.create(frequencyFirst, frequencyLast);
}
@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.grace_period": "Grace Period",
"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.greater": "More than",
"create.schedule.condition.threshold.less": "Less than",
"create.schedule.condition.threshold.equal": "Exactly",
"create.schedule.condition.threshold.train_holds": "Train holds %1$s",
"create.schedule.condition.threshold.greater": "more than",
"create.schedule.condition.threshold.less": "less than",
"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.matching_content": "Matching Content",
"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.fluid_threshold": "Fluid 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.loop1": "Schedule starts over",
"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