From a1347799af03baa96b6dc92548b41c515a9c14f0 Mon Sep 17 00:00:00 2001 From: simibubi <31564874+simibubi@users.noreply.github.com> Date: Thu, 26 May 2022 19:00:03 +0200 Subject: [PATCH] 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 --- src/generated/resources/.cache/cache | 32 ++-- .../resources/assets/create/lang/en_us.json | 16 +- .../assets/create/lang/unfinished/de_de.json | 18 ++- .../assets/create/lang/unfinished/es_cl.json | 18 ++- .../assets/create/lang/unfinished/es_es.json | 18 ++- .../assets/create/lang/unfinished/fr_fr.json | 18 ++- .../assets/create/lang/unfinished/it_it.json | 18 ++- .../assets/create/lang/unfinished/ja_jp.json | 18 ++- .../assets/create/lang/unfinished/ko_kr.json | 18 ++- .../assets/create/lang/unfinished/nl_nl.json | 18 ++- .../assets/create/lang/unfinished/pl_pl.json | 18 ++- .../assets/create/lang/unfinished/pt_br.json | 18 ++- .../assets/create/lang/unfinished/pt_pt.json | 18 ++- .../assets/create/lang/unfinished/ro_ro.json | 18 ++- .../assets/create/lang/unfinished/ru_ru.json | 18 ++- .../assets/create/lang/unfinished/zh_cn.json | 18 ++- .../assets/create/lang/unfinished/zh_tw.json | 18 ++- .../simibubi/create/compat/jei/CreateJEI.java | 2 + .../compat/jei/GhostIngredientHandler.java | 12 +- .../AbstractContraptionEntity.java | 2 +- .../structureMovement/Contraption.java | 4 + .../MountedStorageManager.java | 70 +++++---- .../train/TrainCargoManager.java | 143 ++++++++++++++++++ .../content/logistics/IRedstoneLinkable.java | 5 +- .../logistics/RedstoneLinkNetworkHandler.java | 27 +++- .../block/display/DisplayLinkScreen.java | 135 +++-------------- .../block/display/source/DisplaySource.java | 4 +- .../source/FillLevelDisplaySource.java | 4 +- .../source/ItemThoughputDisplaySource.java | 4 +- .../source/ScoreboardDisplaySource.java | 4 +- .../source/SingleLineDisplaySource.java | 6 +- .../source/StatTrackingDisplaySource.java | 4 +- .../source/StationSummaryDisplaySource.java | 4 +- .../source/TimeOfDayDisplaySource.java | 4 +- .../source/ValueListDisplaySource.java | 6 +- .../item/LinkedControllerBindPacket.java | 18 +-- .../item/LinkedControllerServerHandler.java | 4 +- .../logistics/trains/entity/Carriage.java | 8 +- .../trains/entity/CarriageContraption.java | 19 ++- .../entity/CarriageContraptionEntity.java | 8 +- .../logistics/trains/entity/Train.java | 13 +- .../management/schedule/IScheduleInput.java | 31 ++-- .../trains/management/schedule/Schedule.java | 2 + .../schedule/ScheduleContainer.java | 31 ++-- .../schedule/ScheduleDataEntry.java | 35 +++++ .../management/schedule/ScheduleRuntime.java | 12 +- .../management/schedule/ScheduleScreen.java | 96 ++++++------ .../condition/CargoThresholdCondition.java | 139 ++++++++--------- .../condition/FluidThresholdCondition.java | 77 +++++++--- .../condition/IdleCargoCondition.java | 14 ++ .../condition/ItemThresholdCondition.java | 102 ++++++++----- .../LazyTickedScheduleCondition.java | 30 ++++ .../condition/RedstoneLinkCondition.java | 121 +++++++++++++++ .../condition/ScheduleWaitCondition.java | 18 +-- .../schedule/condition/ScheduledDelay.java | 5 +- .../condition/StationPoweredCondition.java | 4 +- .../condition/StationUnloadedCondition.java | 4 +- .../condition/TimeOfDayCondition.java | 134 +++++++--------- .../condition/TimedWaitCondition.java | 105 +++++-------- .../destination/ChangeTitleInstruction.java | 4 +- .../destination/DestinationInstruction.java | 21 +-- .../destination/ScheduleInstruction.java | 14 +- .../ScheduleInstructionWithEditBox.java | 69 --------- .../destination/TextScheduleInstruction.java | 37 +++++ .../trains/track/TrackTileEntity.java | 3 - .../foundation/gui/AbstractSimiScreen.java | 21 ++- .../create/foundation/gui/AllGuiTextures.java | 4 +- .../create/foundation/gui/ModularGuiLine.java | 115 ++++++++++++++ .../foundation/gui/ModularGuiLineBuilder.java | 91 +++++++++++ .../AbstractSimiContainerScreen.java | 13 +- .../foundation/gui/widget/ScrollInput.java | 29 +++- .../gui/widget/SelectionScrollInput.java | 8 +- .../behaviour/linked/LinkBehaviour.java | 5 +- .../assets/create/lang/default/interface.json | 16 +- .../create/textures/gui/display_link.png | Bin 1632 -> 1676 bytes .../assets/create/textures/gui/schedule.png | Bin 3368 -> 3364 bytes .../assets/create/textures/gui/schedule_2.png | Bin 2111 -> 2040 bytes 77 files changed, 1415 insertions(+), 823 deletions(-) create mode 100644 src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/TrainCargoManager.java create mode 100644 src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleDataEntry.java create mode 100644 src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/LazyTickedScheduleCondition.java create mode 100644 src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/RedstoneLinkCondition.java delete mode 100644 src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/destination/ScheduleInstructionWithEditBox.java create mode 100644 src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/destination/TextScheduleInstruction.java create mode 100644 src/main/java/com/simibubi/create/foundation/gui/ModularGuiLine.java create mode 100644 src/main/java/com/simibubi/create/foundation/gui/ModularGuiLineBuilder.java diff --git a/src/generated/resources/.cache/cache b/src/generated/resources/.cache/cache index 5782b855f..f2c21c6e8 100644 --- a/src/generated/resources/.cache/cache +++ b/src/generated/resources/.cache/cache @@ -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 diff --git a/src/generated/resources/assets/create/lang/en_us.json b/src/generated/resources/assets/create/lang/en_us.json index 3ecb2f016..e0afc3326 100644 --- a/src/generated/resources/assets/create/lang/en_us.json +++ b/src/generated/resources/assets/create/lang/en_us.json @@ -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", diff --git a/src/generated/resources/assets/create/lang/unfinished/de_de.json b/src/generated/resources/assets/create/lang/unfinished/de_de.json index 9f83ed743..de4e9927d 100644 --- a/src/generated/resources/assets/create/lang/unfinished/de_de.json +++ b/src/generated/resources/assets/create/lang/unfinished/de_de.json @@ -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", diff --git a/src/generated/resources/assets/create/lang/unfinished/es_cl.json b/src/generated/resources/assets/create/lang/unfinished/es_cl.json index cf31a58db..614d5d347 100644 --- a/src/generated/resources/assets/create/lang/unfinished/es_cl.json +++ b/src/generated/resources/assets/create/lang/unfinished/es_cl.json @@ -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", diff --git a/src/generated/resources/assets/create/lang/unfinished/es_es.json b/src/generated/resources/assets/create/lang/unfinished/es_es.json index 51c1ddb83..f90461ead 100644 --- a/src/generated/resources/assets/create/lang/unfinished/es_es.json +++ b/src/generated/resources/assets/create/lang/unfinished/es_es.json @@ -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", diff --git a/src/generated/resources/assets/create/lang/unfinished/fr_fr.json b/src/generated/resources/assets/create/lang/unfinished/fr_fr.json index 9de62c18a..3f8fb45f7 100644 --- a/src/generated/resources/assets/create/lang/unfinished/fr_fr.json +++ b/src/generated/resources/assets/create/lang/unfinished/fr_fr.json @@ -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", diff --git a/src/generated/resources/assets/create/lang/unfinished/it_it.json b/src/generated/resources/assets/create/lang/unfinished/it_it.json index 4ff08b1d9..77d2daa61 100644 --- a/src/generated/resources/assets/create/lang/unfinished/it_it.json +++ b/src/generated/resources/assets/create/lang/unfinished/it_it.json @@ -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", diff --git a/src/generated/resources/assets/create/lang/unfinished/ja_jp.json b/src/generated/resources/assets/create/lang/unfinished/ja_jp.json index bd41afb83..113d0d4ea 100644 --- a/src/generated/resources/assets/create/lang/unfinished/ja_jp.json +++ b/src/generated/resources/assets/create/lang/unfinished/ja_jp.json @@ -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", diff --git a/src/generated/resources/assets/create/lang/unfinished/ko_kr.json b/src/generated/resources/assets/create/lang/unfinished/ko_kr.json index 9d377911b..dc40e5c2c 100644 --- a/src/generated/resources/assets/create/lang/unfinished/ko_kr.json +++ b/src/generated/resources/assets/create/lang/unfinished/ko_kr.json @@ -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", diff --git a/src/generated/resources/assets/create/lang/unfinished/nl_nl.json b/src/generated/resources/assets/create/lang/unfinished/nl_nl.json index 4c2af56ed..4ee7b4f2d 100644 --- a/src/generated/resources/assets/create/lang/unfinished/nl_nl.json +++ b/src/generated/resources/assets/create/lang/unfinished/nl_nl.json @@ -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", diff --git a/src/generated/resources/assets/create/lang/unfinished/pl_pl.json b/src/generated/resources/assets/create/lang/unfinished/pl_pl.json index a3ec73e6d..d708fcb6d 100644 --- a/src/generated/resources/assets/create/lang/unfinished/pl_pl.json +++ b/src/generated/resources/assets/create/lang/unfinished/pl_pl.json @@ -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", diff --git a/src/generated/resources/assets/create/lang/unfinished/pt_br.json b/src/generated/resources/assets/create/lang/unfinished/pt_br.json index 3ec694aa4..4f4a93781 100644 --- a/src/generated/resources/assets/create/lang/unfinished/pt_br.json +++ b/src/generated/resources/assets/create/lang/unfinished/pt_br.json @@ -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", diff --git a/src/generated/resources/assets/create/lang/unfinished/pt_pt.json b/src/generated/resources/assets/create/lang/unfinished/pt_pt.json index b450887be..9a6ada2ef 100644 --- a/src/generated/resources/assets/create/lang/unfinished/pt_pt.json +++ b/src/generated/resources/assets/create/lang/unfinished/pt_pt.json @@ -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", diff --git a/src/generated/resources/assets/create/lang/unfinished/ro_ro.json b/src/generated/resources/assets/create/lang/unfinished/ro_ro.json index ce0237530..585fcafee 100644 --- a/src/generated/resources/assets/create/lang/unfinished/ro_ro.json +++ b/src/generated/resources/assets/create/lang/unfinished/ro_ro.json @@ -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", diff --git a/src/generated/resources/assets/create/lang/unfinished/ru_ru.json b/src/generated/resources/assets/create/lang/unfinished/ru_ru.json index 026add7dc..bcc7d6918 100644 --- a/src/generated/resources/assets/create/lang/unfinished/ru_ru.json +++ b/src/generated/resources/assets/create/lang/unfinished/ru_ru.json @@ -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", diff --git a/src/generated/resources/assets/create/lang/unfinished/zh_cn.json b/src/generated/resources/assets/create/lang/unfinished/zh_cn.json index 0e679bd00..a8a246569 100644 --- a/src/generated/resources/assets/create/lang/unfinished/zh_cn.json +++ b/src/generated/resources/assets/create/lang/unfinished/zh_cn.json @@ -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", diff --git a/src/generated/resources/assets/create/lang/unfinished/zh_tw.json b/src/generated/resources/assets/create/lang/unfinished/zh_tw.json index 7b1f6f5be..003811506 100644 --- a/src/generated/resources/assets/create/lang/unfinished/zh_tw.json +++ b/src/generated/resources/assets/create/lang/unfinished/zh_tw.json @@ -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", diff --git a/src/main/java/com/simibubi/create/compat/jei/CreateJEI.java b/src/main/java/com/simibubi/create/compat/jei/CreateJEI.java index cd5825397..b47f99fb2 100644 --- a/src/main/java/com/simibubi/create/compat/jei/CreateJEI.java +++ b/src/main/java/com/simibubi/create/compat/jei/CreateJEI.java @@ -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> { diff --git a/src/main/java/com/simibubi/create/compat/jei/GhostIngredientHandler.java b/src/main/java/com/simibubi/create/compat/jei/GhostIngredientHandler.java index 58025e657..6dc404182 100644 --- a/src/main/java/com/simibubi/create/compat/jei/GhostIngredientHandler.java +++ b/src/main/java/com/simibubi/create/compat/jei/GhostIngredientHandler.java @@ -20,7 +20,7 @@ import net.minecraft.world.item.ItemStack; @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault public class GhostIngredientHandler> - implements IGhostIngredientHandler> { + implements IGhostIngredientHandler> { @Override public List> getTargets(AbstractSimiContainerScreen gui, I ingredient, boolean doStart) { @@ -29,9 +29,12 @@ public class GhostIngredientHandler> if (ingredient instanceof ItemStack) { for (int i = 36; i < gui.getMenu().slots.size(); i++) { - targets.add(new GhostTarget<>(gui, i - 36, isAttributeFilter)); + if (gui.getMenu().slots.get(i) + .isActive()) + targets.add(new GhostTarget<>(gui, i - 36, isAttributeFilter)); - // Only accept items in 1st slot. 2nd is used for functionality, don't wanna override that one + // Only accept items in 1st slot. 2nd is used for functionality, don't wanna + // override that one if (isAttributeFilter) break; } @@ -41,8 +44,7 @@ public class GhostIngredientHandler> } @Override - public void onComplete() { - } + public void onComplete() {} @Override public boolean shouldHighlightTargets() { diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntity.java index 0484af53e..84feb17d9 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntity.java @@ -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(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/Contraption.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/Contraption.java index 2b6d884f1..27a0f539f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/Contraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/Contraption.java @@ -1290,4 +1290,8 @@ public abstract class Contraption { } } + public void tickStorage(AbstractContraptionEntity entity) { + storage.entityTick(entity); + } + } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MountedStorageManager.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MountedStorageManager.java index 4f95e0175..6d7566867 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MountedStorageManager.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MountedStorageManager.java @@ -30,11 +30,11 @@ import net.minecraftforge.items.IItemHandlerModifiable; public class MountedStorageManager { - private ContraptionInvWrapper inventory; - private ContraptionInvWrapper fuelInventory; - private CombinedTankWrapper fluidInventory; - private Map storage; - private Map fluidStorage; + protected ContraptionInvWrapper inventory; + protected ContraptionInvWrapper fuelInventory; + protected CombinedTankWrapper fluidInventory; + protected Map storage; + protected Map fluidStorage; public MountedStorageManager() { storage = new HashMap<>(); @@ -48,27 +48,29 @@ public class MountedStorageManager { public void createHandlers() { Collection 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 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 list) { + protected ContraptionInvWrapper wrapItems(Collection list, boolean fuel) { return new ContraptionInvWrapper(Arrays.copyOf(list.toArray(), list.size(), IItemHandlerModifiable[].class)); } + protected CombinedTankWrapper wrapFluids(Collection 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,18 +88,7 @@ public class MountedStorageManager { .put(NbtUtils.readBlockPos(c.getCompound("Pos")), MountedFluidStorage.deserialize(c.getCompound("Data")))); if (clientPacket && presentTileEntities != null) - fluidStorage.forEach((pos, mfs) -> { - BlockEntity tileEntity = presentTileEntities.get(pos); - if (!(tileEntity instanceof FluidTankTileEntity)) - return; - FluidTankTileEntity tank = (FluidTankTileEntity) tileEntity; - IFluidTank tankInventory = tank.getTankInventory(); - if (tankInventory instanceof FluidTank) - ((FluidTank) tankInventory).setFluid(mfs.tank.getFluid()); - tank.getFluidLevel() - .startWithValue(tank.getFillState()); - mfs.assignTileEntity(tank); - }); + bindTanks(presentTileEntities); List handlers = new ArrayList<>(); List fuelHandlers = new ArrayList<>(); @@ -108,14 +99,27 @@ public class MountedStorageManager { fuelHandlers.add(itemHandler); } - int index = 0; - IFluidHandler[] fluidHandlers = new IFluidHandler[fluidStorage.size()]; - for (MountedFluidStorage mountedStorage : fluidStorage.values()) - fluidHandlers[index++] = mountedStorage.getFluidHandler(); + inventory = wrapItems(handlers, false); + fuelInventory = wrapItems(fuelHandlers, true); + fluidInventory = wrapFluids(fluidStorage.values() + .stream() + .map(MountedFluidStorage::getFluidHandler) + .toList()); + } - inventory = wrap(handlers); - fuelInventory = wrap(fuelHandlers); - fluidInventory = new CombinedTankWrapper(fluidHandlers); + public void bindTanks(Map presentTileEntities) { + fluidStorage.forEach((pos, mfs) -> { + BlockEntity tileEntity = presentTileEntities.get(pos); + if (!(tileEntity instanceof FluidTankTileEntity)) + return; + FluidTankTileEntity tank = (FluidTankTileEntity) tileEntity; + IFluidTank tankInventory = tank.getTankInventory(); + if (tankInventory instanceof FluidTank) + ((FluidTank) tankInventory).setFluid(mfs.tank.getFluid()); + tank.getFluidLevel() + .startWithValue(tank.getFillState()); + mfs.assignTileEntity(tank); + }); } public void write(CompoundTag nbt, boolean clientPacket) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/TrainCargoManager.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/TrainCargoManager.java new file mode 100644 index 000000000..5d8561369 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/TrainCargoManager.java @@ -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 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 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 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; + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/IRedstoneLinkable.java b/src/main/java/com/simibubi/create/content/logistics/IRedstoneLinkable.java index a881f4a0f..1fa782796 100644 --- a/src/main/java/com/simibubi/create/content/logistics/IRedstoneLinkable.java +++ b/src/main/java/com/simibubi/create/content/logistics/IRedstoneLinkable.java @@ -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 getNetworkKey(); + public Couple getNetworkKey(); public BlockPos getLocation(); diff --git a/src/main/java/com/simibubi/create/content/logistics/RedstoneLinkNetworkHandler.java b/src/main/java/com/simibubi/create/content/logistics/RedstoneLinkNetworkHandler.java index 098ce17b4..b4890d6ac 100644 --- a/src/main/java/com/simibubi/create/content/logistics/RedstoneLinkNetworkHandler.java +++ b/src/main/java/com/simibubi/create/content/logistics/RedstoneLinkNetworkHandler.java @@ -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,8 +21,10 @@ import net.minecraft.world.level.LevelAccessor; public class RedstoneLinkNetworkHandler { - static final Map, Set>> connections = + static final Map, Set>> connections = new IdentityHashMap<>(); + + public final AtomicInteger globalPowerVersion = new AtomicInteger(); public static class Frequency { public static final Frequency EMPTY = new Frequency(ItemStack.EMPTY); @@ -76,8 +78,8 @@ public class RedstoneLinkNetworkHandler { } public Set getNetworkOf(LevelAccessor world, IRedstoneLinkable actor) { - Map, Set> networksInWorld = networksIn(world); - Pair key = actor.getNetworkKey(); + Map, Set> networksInWorld = networksIn(world); + Couple 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 network = getNetworkOf(world, actor); + globalPowerVersion.incrementAndGet(); int power = 0; for (Iterator iterator = network.iterator(); iterator.hasNext();) { @@ -141,7 +144,7 @@ public class RedstoneLinkNetworkHandler { .closerThan(to.getLocation(), AllConfigs.SERVER.logistics.linkRange.get()); } - public Map, Set> networksIn(LevelAccessor world) { + public Map, Set> 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) { + for (Map, Set> map : connections.values()) { + Set set = map.get(frequency); + if (set == null || set.isEmpty()) + continue; + for (IRedstoneLinkable link : set) + if (link.getTransmittedStrength() > 0) + return true; + } + return false; + } + } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/DisplayLinkScreen.java b/src/main/java/com/simibubi/create/content/logistics/block/display/DisplayLinkScreen.java index b91b50ba7..261238073 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/DisplayLinkScreen.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/display/DisplayLinkScreen.java @@ -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>> configWidgets; + Couple 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; @@ -178,100 +172,22 @@ public class DisplayLinkScreen extends AbstractSimiScreen { private void initGathererSourceSubOptions(int i) { DisplaySource source = sources.get(i); source.populateData(new DisplayLinkContext(te.getLevel(), te)); - + if (targetLineSelector != null) targetLineSelector .titled(source instanceof SingleLineDisplaySource ? Lang.translate("display_link.display_on") : 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> targetSet; - private int x; - private int y; - - public LineBuilder(Set> targetSet, int x, int y) { - this.targetSet = targetSet; - this.x = x; - this.y = y; - } - - public LineBuilder addScrollInput(int x, int width, BiConsumer 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 inputTransform, String dataKey) { - SelectionScrollInput input = new SelectionScrollInput(x + this.x, y - 4, width, 18); - addScrollInput(input, inputTransform, dataKey); - return this; - } - - private void addScrollInput(T input, BiConsumer 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 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 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 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); diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/source/DisplaySource.java b/src/main/java/com/simibubi/create/content/logistics/block/display/source/DisplaySource.java index 8a0c8042b..0e3fb583d 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/source/DisplaySource.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/display/source/DisplaySource.java @@ -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) {} } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/source/FillLevelDisplaySource.java b/src/main/java/com/simibubi/create/content/logistics/block/display/source/FillLevelDisplaySource.java index 910a72dd1..b35a7637c 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/source/FillLevelDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/display/source/FillLevelDisplaySource.java @@ -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; diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/source/ItemThoughputDisplaySource.java b/src/main/java/com/simibubi/create/content/logistics/block/display/source/ItemThoughputDisplaySource.java index 05be1f045..cf35535d6 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/source/ItemThoughputDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/display/source/ItemThoughputDisplaySource.java @@ -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; diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/source/ScoreboardDisplaySource.java b/src/main/java/com/simibubi/create/content/logistics/block/display/source/ScoreboardDisplaySource.java index 44f4c7f79..ea483710f 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/source/ScoreboardDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/display/source/ScoreboardDisplaySource.java @@ -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(""); diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/source/SingleLineDisplaySource.java b/src/main/java/com/simibubi/create/content/logistics/block/display/source/SingleLineDisplaySource.java index e372564f7..a36878d83 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/source/SingleLineDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/display/source/SingleLineDisplaySource.java @@ -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") diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/source/StatTrackingDisplaySource.java b/src/main/java/com/simibubi/create/content/logistics/block/display/source/StatTrackingDisplaySource.java index 9b3e80c33..c4f15525c 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/source/StatTrackingDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/display/source/StatTrackingDisplaySource.java @@ -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) {} } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/source/StationSummaryDisplaySource.java b/src/main/java/com/simibubi/create/content/logistics/block/display/source/StationSummaryDisplaySource.java index 0c3b86245..e53496982 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/source/StationSummaryDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/display/source/StationSummaryDisplaySource.java @@ -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(""); diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/source/TimeOfDayDisplaySource.java b/src/main/java/com/simibubi/create/content/logistics/block/display/source/TimeOfDayDisplaySource.java index 125a12deb..1e69402f7 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/source/TimeOfDayDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/display/source/TimeOfDayDisplaySource.java @@ -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; diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/source/ValueListDisplaySource.java b/src/main/java/com/simibubi/create/content/logistics/block/display/source/ValueListDisplaySource.java index a6baa8309..07134b12a 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/source/ValueListDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/display/source/ValueListDisplaySource.java @@ -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")), diff --git a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerBindPacket.java b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerBindPacket.java index 1b492288e..2af7d8555 100644 --- a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerBindPacket.java +++ b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerBindPacket.java @@ -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,18 +43,15 @@ public class LinkedControllerBindPacket extends LinkedControllerPacketBase { if (linkBehaviour == null) return; - Pair 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 - protected void handleLectern(ServerPlayer player, LecternControllerTileEntity lectern) { } + protected void handleLectern(ServerPlayer player, LecternControllerTileEntity lectern) {} } diff --git a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerServerHandler.java b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerServerHandler.java index 0f0ece673..d715dcdb1 100644 --- a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerServerHandler.java +++ b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerServerHandler.java @@ -114,8 +114,8 @@ public class LinkedControllerServerHandler { } @Override - public Pair getNetworkKey() { - return Pair.of(getSecond().getFirst(), getSecond().getSecond()); + public Couple getNetworkKey() { + return getSecond(); } } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/Carriage.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/Carriage.java index 25c90eb6f..4d3cb2fb6 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/Carriage.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/Carriage.java @@ -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 bogeys; - public MountedStorageManager storage; + public TrainCargoManager storage; CompoundTag serialisedEntity; Map 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; @@ -775,7 +775,7 @@ public class Carriage { cce.setGraph(train.graph == null ? null : train.graph.id); cce.setCarriage(Carriage.this); cce.syncCarriage(); - + if (level instanceof ServerLevel sl) sl.addFreshEntity(entity); diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraption.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraption.java index 717e222b1..e6535b62b 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraption.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraption.java @@ -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,12 +131,12 @@ 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; } - + public void returnStorageForDisassembly(MountedStorageManager storage) { this.storage = 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); + } } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraptionEntity.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraptionEntity.java index 04e71c032..d82e2de8b 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraptionEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraptionEntity.java @@ -133,7 +133,7 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity { } public boolean isLocalCoordWithin(BlockPos localPos, int min, int max) { - if (!(getContraption()instanceof CarriageContraption cc)) + if (!(getContraption() instanceof CarriageContraption cc)) return false; Direction facing = cc.getAssemblyDirection(); Axis axis = facing.getClockWise() @@ -186,6 +186,8 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity { dimensional.pivot = null; carriage.updateContraptionAnchors(); dimensional.updateRenderedCutoff(); + + carriage.storage.bindTanks(contraption.presentTileEntities); } updateTrackGraph(); } else @@ -497,7 +499,7 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity { if (targetSpeed != 0) carriage.train.burnFuel(); - + boolean slow = inverted ^ targetSpeed < 0; boolean spaceDown = heldControls.contains(4); GlobalStation currentStation = carriage.train.getCurrentStation(); @@ -611,7 +613,7 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity { this.carriageIndex = carriage.train.carriages.indexOf(carriage); if (contraption instanceof CarriageContraption cc) cc.swapStorageAfterAssembly(this); - + DimensionalCarriageEntity dimensional = carriage.getDimensional(level); dimensional.pivot = null; carriage.updateContraptionAnchors(); diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/Train.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/Train.java index 7697883a9..2332068e2 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/Train.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/Train.java @@ -169,6 +169,9 @@ public class Train { updateConductors(); return; } + + if (heldForAssembly && getCurrentStation() == null) + heldForAssembly = false; updateConductors(); runtime.tick(level); @@ -290,7 +293,7 @@ public class Train { public IEdgePointListener frontSignalListener() { return (distance, couple) -> { - if (couple.getFirst()instanceof GlobalStation station) { + if (couple.getFirst() instanceof GlobalStation station) { if (!station.canApproachFrom(couple.getSecond() .getSecond()) || navigation.destination != station) return false; @@ -302,7 +305,7 @@ public class Train { return true; } - if (!(couple.getFirst()instanceof SignalBoundary signal)) + if (!(couple.getFirst() instanceof SignalBoundary signal)) return false; if (navigation.waitingForSignal != null && navigation.waitingForSignal.getFirst() .equals(signal.id)) { @@ -333,7 +336,7 @@ public class Train { public IEdgePointListener backSignalListener() { return (distance, couple) -> { - if (!(couple.getFirst()instanceof SignalBoundary signal)) + if (!(couple.getFirst() instanceof SignalBoundary signal)) return false; UUID groupId = signal.getGroup(couple.getSecond() .getFirst()); @@ -547,7 +550,7 @@ public class Train { if (entity == null) return false; - if (entity.getContraption()instanceof CarriageContraption cc) + if (entity.getContraption() instanceof CarriageContraption cc) cc.returnStorageForDisassembly(carriage.storage); entity.setPos(Vec3 .atLowerCornerOf(pos.relative(assemblyDirection, backwards ? offset + carriage.bogeySpacing : offset))); @@ -813,7 +816,7 @@ public class Train { forEachTravellingPointBackwards((tp, d) -> { signalScout.travel(graph, d, signalScout.follow(tp), (distance, couple) -> { - if (!(couple.getFirst()instanceof SignalBoundary signal)) + if (!(couple.getFirst() instanceof SignalBoundary signal)) return false; couple.getSecond() .map(signal::getGroup) diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/IScheduleInput.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/IScheduleInput.java index dc0e583e9..85c1b0fe8 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/IScheduleInput.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/IScheduleInput.java @@ -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>> editorSubWidgets, - List dividers, int x, int y) {} + public default int slotsTargeted() { + return 0; + } public default List 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 getSecondLineTooltip() { + public default List 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; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/Schedule.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/Schedule.java index cdf7c0b0a..289b0957b 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/Schedule.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/Schedule.java @@ -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); diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleContainer.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleContainer.java index 941572039..15f456bbb 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleContainer.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleContainer.java @@ -17,8 +17,10 @@ import net.minecraftforge.items.SlotItemHandler; public class ScheduleContainer extends GhostItemContainer { 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 { @Override protected ItemStackHandler createGhostInventory() { - return new ItemStackHandler(1); + return new ItemStackHandler(slots); } @Override @@ -51,9 +53,10 @@ public class ScheduleContainer extends GhostItemContainer { @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 protected void addPlayerSlots(int x, int y) { for (int hotbarSlot = 0; hotbarSlot < 9; ++hotbarSlot) @@ -70,31 +73,35 @@ public class ScheduleContainer extends GhostItemContainer { public boolean stillValid(Player player) { return playerInventory.getSelected() == contentHolder; } - + class InactiveSlot extends Slot { public InactiveSlot(Container pContainer, int pIndex, int pX, int pY) { super(pContainer, pIndex, pX, pY); } - + @Override public boolean isActive() { return slotsActive; } - + } - + 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; } - + } } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleDataEntry.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleDataEntry.java new file mode 100644 index 000000000..58b2eae7a --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleDataEntry.java @@ -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 enumData(String key, Class 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); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleRuntime.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleRuntime.java index b4a8dcd9c..d1f2f087b 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleRuntime.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleRuntime.java @@ -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 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 } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleScreen.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleScreen.java index 61a973f9a..ae0457e6f 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleScreen.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleScreen.java @@ -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 onEditorClose; - private List>> editorSubWidgets; - private List editorDividers; private DestinationSuggestions destinationSuggestions; @@ -104,7 +102,7 @@ public class ScheduleScreen extends AbstractSimiContainerScreen(); + editorSubWidgets = new ModularGuiLine(); } @Override @@ -178,7 +176,13 @@ public class ScheduleScreen extends AbstractSimiContainerScreen 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 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 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,16 +1000,21 @@ public class ScheduleScreen extends AbstractSimiContainerScreen= x + 18 || mouseY >= y + 18) + if (mouseX < x || mouseY < y || mouseX >= x + 120 || mouseY >= y + 18) return; + IScheduleInput rendered = editingCondition == null ? editingDestination : editingCondition; - List secondLineTooltip = rendered.getSecondLineTooltip(); - if (secondLineTooltip == null || (hoveredSlot != null && !hoveredSlot.getItem() - .isEmpty())) - return; - renderTooltip(matrixStack, secondLineTooltip, Optional.empty(), mouseX, mouseY); + + for (int i = 0; i < Math.max(1, rendered.slotsTargeted()); i++) { + List secondLineTooltip = rendered.getSecondLineTooltip(i); + if (secondLineTooltip == null || (hoveredSlot != menu.getSlot(36 + i) || !hoveredSlot.getItem() + .isEmpty())) + continue; + renderTooltip(matrixStack, secondLineTooltip, Optional.empty(), mouseX, mouseY); + } } @Override @@ -1042,7 +1042,11 @@ public class ScheduleScreen extends AbstractSimiContainerScreen summary = rendered.getSummary(); ItemStack icon = summary.getFirst(); if (icon.isEmpty()) @@ -1055,12 +1059,10 @@ public class ScheduleScreen extends AbstractSimiContainerScreen"), 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 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 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 getSecondLineTooltip() { + public List 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>> editorSubWidgets, - List 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()) - .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); + public void initConfigurationWidgets(ModularGuiLineBuilder builder) { + builder.addSelectionScrollInput(0, 24, (i, l) -> { + i.forOptions(Ops.translatedOptions()) + .titled(Lang.translate("schedule.condition.threshold.train_holds")) + .format(state -> new TextComponent(" " + Ops.values()[state].formatted)); + }, "Operator"); + builder.addIntegerTextInput(29, 41, (e, t) -> { + }, "Threshold"); } + } \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/FluidThresholdCondition.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/FluidThresholdCondition.java index 219f172e4..10c775508 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/FluidThresholdCondition.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/FluidThresholdCondition.java @@ -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 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>> editorSubWidgets, - List dividers, int x, int y) { - super.createWidgets(screen, editorSubWidgets, dividers, x, y); - - 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) -> { - })); + 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"); } + } \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/IdleCargoCondition.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/IdleCargoCondition.java index 31abca86a..721831e13 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/IdleCargoCondition.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/IdleCargoCondition.java @@ -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 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(); + } + } \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/ItemThresholdCondition.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/ItemThresholdCondition.java index f455dbe4e..ef1de352d 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/ItemThresholdCondition.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/ItemThresholdCondition.java @@ -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 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>> editorSubWidgets, - List 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"); } } \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/LazyTickedScheduleCondition.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/LazyTickedScheduleCondition.java new file mode 100644 index 000000000..ce17a254a --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/LazyTickedScheduleCondition.java @@ -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); + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/RedstoneLinkCondition.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/RedstoneLinkCondition.java new file mode 100644 index 000000000..be5803a66 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/RedstoneLinkCondition.java @@ -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 freq; + + public RedstoneLinkCondition() { + freq = Couple.create(() -> Frequency.EMPTY); + } + + @Override + public int slotsTargeted() { + return 2; + } + + @Override + public Pair 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 getSecondLineTooltip(int slot) { + return ImmutableList.of(Lang.translate(slot == 0 ? "logistics.firstFrequency" : "logistics.secondFrequency") + .withStyle(ChatFormatting.RED)); + } + + @Override + public List 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"); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/ScheduleWaitCondition.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/ScheduleWaitCondition.java index 0bd68e12a..06245cc7f 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/ScheduleWaitCondition.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/ScheduleWaitCondition.java @@ -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; } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/ScheduledDelay.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/ScheduledDelay.java index 3877d9304..8f84b76e7 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/ScheduledDelay.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/ScheduledDelay.java @@ -12,15 +12,16 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; public class ScheduledDelay extends TimedWaitCondition { + @Override public Pair getSummary() { return Pair.of(ItemStack.EMPTY, Lang.translate("schedule.condition.delay_short", formatTime(true))); } - + @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; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/StationPoweredCondition.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/StationPoweredCondition.java index ddb953e8c..f2bc319ea 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/StationPoweredCondition.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/StationPoweredCondition.java @@ -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() { diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/StationUnloadedCondition.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/StationUnloadedCondition.java index 8b138bd57..149ed4844 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/StationUnloadedCondition.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/StationUnloadedCondition.java @@ -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() { diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/TimeOfDayCondition.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/TimeOfDayCondition.java index 59f902996..0d6abe887 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/TimeOfDayCondition.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/TimeOfDayCondition.java @@ -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 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 getSecondLineTooltip() { - return super.getSecondLineTooltip(); - } - @Override public List 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>> editorSubWidgets, - List dividers, int x, int y) { - super.createWidgets(screen, editorSubWidgets, dividers, x, y); + public void initConfigurationWidgets(ModularGuiLineBuilder builder) { + MutableObject minuteInput = new MutableObject<>(); + MutableObject hourInput = new MutableObject<>(); + MutableObject