From 141a4069ddc504e3d9a71e984438dc3cce449fb6 Mon Sep 17 00:00:00 2001 From: simibubi <31564874+simibubi@users.noreply.github.com> Date: Sat, 11 Jun 2022 18:54:10 +0200 Subject: [PATCH] Approachable - Station approach/arrival prompt is now more visible --- src/generated/resources/.cache/cache | 32 +++++------ .../resources/assets/create/lang/en_us.json | 3 +- .../assets/create/lang/unfinished/de_de.json | 5 +- .../assets/create/lang/unfinished/es_cl.json | 5 +- .../assets/create/lang/unfinished/es_es.json | 5 +- .../assets/create/lang/unfinished/fr_fr.json | 5 +- .../assets/create/lang/unfinished/it_it.json | 5 +- .../assets/create/lang/unfinished/ja_jp.json | 5 +- .../assets/create/lang/unfinished/ko_kr.json | 5 +- .../assets/create/lang/unfinished/nl_nl.json | 5 +- .../assets/create/lang/unfinished/pl_pl.json | 5 +- .../assets/create/lang/unfinished/pt_br.json | 5 +- .../assets/create/lang/unfinished/pt_pt.json | 5 +- .../assets/create/lang/unfinished/ro_ro.json | 5 +- .../assets/create/lang/unfinished/ru_ru.json | 5 +- .../assets/create/lang/unfinished/zh_cn.json | 5 +- .../assets/create/lang/unfinished/zh_tw.json | 5 +- .../interaction/controls/TrainHUD.java | 42 +++++++++++++++ .../BlazeBurnerInteractionBehaviour.java | 5 -- .../logistics/trains/RailwaySavedData.java | 4 +- .../entity/CarriageContraptionEntity.java | 43 ++++++++------- .../logistics/trains/entity/Train.java | 7 --- .../logistics/trains/entity/TrainPacket.java | 2 - .../trains/entity/TrainPromptPacket.java | 51 ++++++++++++++++++ .../trains/entity/TrainRelocator.java | 1 - .../edgePoint/station/AssemblyScreen.java | 44 +++++---------- .../edgePoint/station/StationEditPacket.java | 9 +++- .../edgePoint/station/StationScreen.java | 10 ++-- .../edgePoint/station/StationTileEntity.java | 7 ++- .../edgePoint/station/TrainEditPacket.java | 14 ++--- .../management/schedule/ScheduleItem.java | 5 -- .../management/schedule/ScheduleRuntime.java | 19 ++++--- .../create/foundation/gui/AllGuiTextures.java | 3 ++ .../foundation/networking/AllPackets.java | 2 + .../assets/create/lang/default/interface.json | 3 +- .../assets/create/textures/gui/widgets.png | Bin 9720 -> 9985 bytes 36 files changed, 232 insertions(+), 149 deletions(-) create mode 100644 src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainPromptPacket.java diff --git a/src/generated/resources/.cache/cache b/src/generated/resources/.cache/cache index df85b3731..b8d6ded11 100644 --- a/src/generated/resources/.cache/cache +++ b/src/generated/resources/.cache/cache @@ -554,22 +554,22 @@ bf2b0310500213ff853c748c236eb5d01f61658e assets/create/blockstates/yellow_toolbo 7f39521b211441f5c3e06d60c5978cebe16cacfb assets/create/blockstates/zinc_block.json b7181bcd8182b2f17088e5aa881f374c9c65470c assets/create/blockstates/zinc_ore.json 50f7862ded2d9a955c259a12685906a9ec9ad97a assets/create/lang/en_ud.json -e0e9ceb9e8fed94c6cd3d3c1066dbf3ca0853e88 assets/create/lang/en_us.json -84bbc4114d730451c9e675409074dba365e607c6 assets/create/lang/unfinished/de_de.json -448116a990ffa8d3c592d119ea86bd9877a0026d assets/create/lang/unfinished/es_cl.json -2b9281ea5066d5c4450cbbbe63dfca8b1f4d46ba assets/create/lang/unfinished/es_es.json -7eba8e0309dfa9ced561cb850e353386b47cd67b assets/create/lang/unfinished/fr_fr.json -621e146bcfb9df8b85f1fa75d696f3a0aedcc5dc assets/create/lang/unfinished/it_it.json -ca96955d0c41de07ac957b0ab39797968138ca74 assets/create/lang/unfinished/ja_jp.json -7b9fea6577fb5c0cd8f7a7c6d6f6c4f81a16ea26 assets/create/lang/unfinished/ko_kr.json -e03cde766aca575ebd98dab10616d99df7a0b104 assets/create/lang/unfinished/nl_nl.json -35c9b916519c89b65c7fb259ccd949d44bcd9f7f assets/create/lang/unfinished/pl_pl.json -6e5c551c7d195c5e3ad7238de6b8827cbbcabeaf assets/create/lang/unfinished/pt_br.json -4c5f43461b221af80e4877619f3142feea125ec0 assets/create/lang/unfinished/pt_pt.json -528524de3e35ea7b063d9acbacea9b608d7766ea assets/create/lang/unfinished/ro_ro.json -fe42e45c945dd298bf09b7e90de1075a52d6210f assets/create/lang/unfinished/ru_ru.json -03a4cfd0612beebf3842607cba2d898844478699 assets/create/lang/unfinished/zh_cn.json -ea95d915b70139d73dc413af69d502759e882672 assets/create/lang/unfinished/zh_tw.json +a768ce262b1d113b915306b93805121e6d6f3934 assets/create/lang/en_us.json +c2f79787186fc4ac21c5b357c642e1ab04443411 assets/create/lang/unfinished/de_de.json +abdf065efd476eea939956f2b7d59d9b10df1280 assets/create/lang/unfinished/es_cl.json +1971ba8276f31d0e8af81089a15888038197e858 assets/create/lang/unfinished/es_es.json +ea67e13386220b980c0a0245410c2e3d2c845d35 assets/create/lang/unfinished/fr_fr.json +38c181d840e33f6a277876b6cf4db95a2ef15262 assets/create/lang/unfinished/it_it.json +7e54413e3920b0f4ffc2363d5c521735a177e295 assets/create/lang/unfinished/ja_jp.json +4d3696fa3de235b23d1b29a05a56c495ff11930c assets/create/lang/unfinished/ko_kr.json +7f0e6420fc7685523795aca3c87a12df7029e0cc assets/create/lang/unfinished/nl_nl.json +fb286ebb45b6e191c9357085df2fb21061bed70b assets/create/lang/unfinished/pl_pl.json +269439ab8d7277eb445f76f52342a3b7b72f812c assets/create/lang/unfinished/pt_br.json +6bddc9fc7ae5186747521496d21d0226cc23b01b assets/create/lang/unfinished/pt_pt.json +f7704e9e3200b614c60410feca6c83742d42177d assets/create/lang/unfinished/ro_ro.json +c445375f72f9205d119741c4784e9383020bde10 assets/create/lang/unfinished/ru_ru.json +8986740c8eec44cfe805f7cb242232105369f8fa assets/create/lang/unfinished/zh_cn.json +5c4f08c71c49ab13e9b17e2c1106e5a575448cfc 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 a353c836d..09232eff6 100644 --- a/src/generated/resources/assets/create/lang/en_us.json +++ b/src/generated/resources/assets/create/lang/en_us.json @@ -1436,7 +1436,6 @@ "create.schedule.loop2": "when completed", "create.schedule.reset": "Reset Progress", "create.schedule.skip": "Skip current Stop", - "create.schedule.train_still_assembling": "Confirm Train Assembly in the Station UI first", "create.schedule.applied_to_train": "Train is now following this Schedule", "create.schedule.non_controlling_seat": "Conductor needs to sit in front of a Controls block", "create.schedule.remove_with_empty_hand": "Remove current Schedule with an Empty Hand", @@ -1507,6 +1506,8 @@ "create.train.relocate.valid": "Can relocate to here, Click to Confirm", "create.train.relocate.invalid": "Cannot relocate Train to here", "create.train.relocate.too_far": "Cannot relocate Train this far away", + "create.train.departing_from": "Departing from %1$s", + "create.train.arrived_at": "Arrived at %1$s", "create.track_signal.cannot_change_mode": "Unable to switch mode of this Signal", "create.track_signal.mode_change.entry_signal": "-> Allow passage if section unoccupied", 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 86478cd0f..8401af1ae 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: 981", + "_": "Missing Localizations: 982", "_": "->------------------------] Game Elements [------------------------<-", @@ -1437,7 +1437,6 @@ "create.schedule.loop2": "UNLOCALIZED: when completed", "create.schedule.reset": "UNLOCALIZED: Reset Progress", "create.schedule.skip": "UNLOCALIZED: Skip current Stop", - "create.schedule.train_still_assembling": "UNLOCALIZED: Confirm Train Assembly in the Station UI first", "create.schedule.applied_to_train": "UNLOCALIZED: Train is now following this Schedule", "create.schedule.non_controlling_seat": "UNLOCALIZED: Conductor needs to sit in front of a Controls block", "create.schedule.remove_with_empty_hand": "UNLOCALIZED: Remove current Schedule with an Empty Hand", @@ -1508,6 +1507,8 @@ "create.train.relocate.valid": "UNLOCALIZED: Can relocate to here, Click to Confirm", "create.train.relocate.invalid": "UNLOCALIZED: Cannot relocate Train to here", "create.train.relocate.too_far": "UNLOCALIZED: Cannot relocate Train this far away", + "create.train.departing_from": "UNLOCALIZED: Departing from %1$s", + "create.train.arrived_at": "UNLOCALIZED: Arrived at %1$s", "create.track_signal.cannot_change_mode": "UNLOCALIZED: Unable to switch mode of this Signal", "create.track_signal.mode_change.entry_signal": "UNLOCALIZED: -> Allow passage if section unoccupied", 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 89585a651..1675e3069 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: 631", + "_": "Missing Localizations: 632", "_": "->------------------------] Game Elements [------------------------<-", @@ -1437,7 +1437,6 @@ "create.schedule.loop2": "UNLOCALIZED: when completed", "create.schedule.reset": "UNLOCALIZED: Reset Progress", "create.schedule.skip": "UNLOCALIZED: Skip current Stop", - "create.schedule.train_still_assembling": "UNLOCALIZED: Confirm Train Assembly in the Station UI first", "create.schedule.applied_to_train": "UNLOCALIZED: Train is now following this Schedule", "create.schedule.non_controlling_seat": "UNLOCALIZED: Conductor needs to sit in front of a Controls block", "create.schedule.remove_with_empty_hand": "UNLOCALIZED: Remove current Schedule with an Empty Hand", @@ -1508,6 +1507,8 @@ "create.train.relocate.valid": "UNLOCALIZED: Can relocate to here, Click to Confirm", "create.train.relocate.invalid": "UNLOCALIZED: Cannot relocate Train to here", "create.train.relocate.too_far": "UNLOCALIZED: Cannot relocate Train this far away", + "create.train.departing_from": "UNLOCALIZED: Departing from %1$s", + "create.train.arrived_at": "UNLOCALIZED: Arrived at %1$s", "create.track_signal.cannot_change_mode": "UNLOCALIZED: Unable to switch mode of this Signal", "create.track_signal.mode_change.entry_signal": "UNLOCALIZED: -> Allow passage if section unoccupied", 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 1ec0e36e2..1b69a5800 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: 295", + "_": "Missing Localizations: 296", "_": "->------------------------] Game Elements [------------------------<-", @@ -1437,7 +1437,6 @@ "create.schedule.loop2": "UNLOCALIZED: when completed", "create.schedule.reset": "UNLOCALIZED: Reset Progress", "create.schedule.skip": "UNLOCALIZED: Skip current Stop", - "create.schedule.train_still_assembling": "UNLOCALIZED: Confirm Train Assembly in the Station UI first", "create.schedule.applied_to_train": "UNLOCALIZED: Train is now following this Schedule", "create.schedule.non_controlling_seat": "UNLOCALIZED: Conductor needs to sit in front of a Controls block", "create.schedule.remove_with_empty_hand": "UNLOCALIZED: Remove current Schedule with an Empty Hand", @@ -1508,6 +1507,8 @@ "create.train.relocate.valid": "UNLOCALIZED: Can relocate to here, Click to Confirm", "create.train.relocate.invalid": "UNLOCALIZED: Cannot relocate Train to here", "create.train.relocate.too_far": "UNLOCALIZED: Cannot relocate Train this far away", + "create.train.departing_from": "UNLOCALIZED: Departing from %1$s", + "create.train.arrived_at": "UNLOCALIZED: Arrived at %1$s", "create.track_signal.cannot_change_mode": "UNLOCALIZED: Unable to switch mode of this Signal", "create.track_signal.mode_change.entry_signal": "UNLOCALIZED: -> Allow passage if section unoccupied", 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 11f50da83..d00d4dac3 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: 1869", + "_": "Missing Localizations: 1870", "_": "->------------------------] Game Elements [------------------------<-", @@ -1437,7 +1437,6 @@ "create.schedule.loop2": "UNLOCALIZED: when completed", "create.schedule.reset": "UNLOCALIZED: Reset Progress", "create.schedule.skip": "UNLOCALIZED: Skip current Stop", - "create.schedule.train_still_assembling": "UNLOCALIZED: Confirm Train Assembly in the Station UI first", "create.schedule.applied_to_train": "UNLOCALIZED: Train is now following this Schedule", "create.schedule.non_controlling_seat": "UNLOCALIZED: Conductor needs to sit in front of a Controls block", "create.schedule.remove_with_empty_hand": "UNLOCALIZED: Remove current Schedule with an Empty Hand", @@ -1508,6 +1507,8 @@ "create.train.relocate.valid": "UNLOCALIZED: Can relocate to here, Click to Confirm", "create.train.relocate.invalid": "UNLOCALIZED: Cannot relocate Train to here", "create.train.relocate.too_far": "UNLOCALIZED: Cannot relocate Train this far away", + "create.train.departing_from": "UNLOCALIZED: Departing from %1$s", + "create.train.arrived_at": "UNLOCALIZED: Arrived at %1$s", "create.track_signal.cannot_change_mode": "UNLOCALIZED: Unable to switch mode of this Signal", "create.track_signal.mode_change.entry_signal": "UNLOCALIZED: -> Allow passage if section unoccupied", 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 a9b8da948..41729b010 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: 1558", + "_": "Missing Localizations: 1559", "_": "->------------------------] Game Elements [------------------------<-", @@ -1437,7 +1437,6 @@ "create.schedule.loop2": "UNLOCALIZED: when completed", "create.schedule.reset": "UNLOCALIZED: Reset Progress", "create.schedule.skip": "UNLOCALIZED: Skip current Stop", - "create.schedule.train_still_assembling": "UNLOCALIZED: Confirm Train Assembly in the Station UI first", "create.schedule.applied_to_train": "UNLOCALIZED: Train is now following this Schedule", "create.schedule.non_controlling_seat": "UNLOCALIZED: Conductor needs to sit in front of a Controls block", "create.schedule.remove_with_empty_hand": "UNLOCALIZED: Remove current Schedule with an Empty Hand", @@ -1508,6 +1507,8 @@ "create.train.relocate.valid": "UNLOCALIZED: Can relocate to here, Click to Confirm", "create.train.relocate.invalid": "UNLOCALIZED: Cannot relocate Train to here", "create.train.relocate.too_far": "UNLOCALIZED: Cannot relocate Train this far away", + "create.train.departing_from": "UNLOCALIZED: Departing from %1$s", + "create.train.arrived_at": "UNLOCALIZED: Arrived at %1$s", "create.track_signal.cannot_change_mode": "UNLOCALIZED: Unable to switch mode of this Signal", "create.track_signal.mode_change.entry_signal": "UNLOCALIZED: -> Allow passage if section unoccupied", 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 9ab09eb8b..f64862f52 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: 297", + "_": "Missing Localizations: 298", "_": "->------------------------] Game Elements [------------------------<-", @@ -1437,7 +1437,6 @@ "create.schedule.loop2": "UNLOCALIZED: when completed", "create.schedule.reset": "UNLOCALIZED: Reset Progress", "create.schedule.skip": "UNLOCALIZED: Skip current Stop", - "create.schedule.train_still_assembling": "UNLOCALIZED: Confirm Train Assembly in the Station UI first", "create.schedule.applied_to_train": "UNLOCALIZED: Train is now following this Schedule", "create.schedule.non_controlling_seat": "UNLOCALIZED: Conductor needs to sit in front of a Controls block", "create.schedule.remove_with_empty_hand": "UNLOCALIZED: Remove current Schedule with an Empty Hand", @@ -1508,6 +1507,8 @@ "create.train.relocate.valid": "UNLOCALIZED: Can relocate to here, Click to Confirm", "create.train.relocate.invalid": "UNLOCALIZED: Cannot relocate Train to here", "create.train.relocate.too_far": "UNLOCALIZED: Cannot relocate Train this far away", + "create.train.departing_from": "UNLOCALIZED: Departing from %1$s", + "create.train.arrived_at": "UNLOCALIZED: Arrived at %1$s", "create.track_signal.cannot_change_mode": "UNLOCALIZED: Unable to switch mode of this Signal", "create.track_signal.mode_change.entry_signal": "UNLOCALIZED: -> Allow passage if section unoccupied", 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 98a39e242..c906a6c84 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: 297", + "_": "Missing Localizations: 298", "_": "->------------------------] Game Elements [------------------------<-", @@ -1437,7 +1437,6 @@ "create.schedule.loop2": "UNLOCALIZED: when completed", "create.schedule.reset": "UNLOCALIZED: Reset Progress", "create.schedule.skip": "UNLOCALIZED: Skip current Stop", - "create.schedule.train_still_assembling": "UNLOCALIZED: Confirm Train Assembly in the Station UI first", "create.schedule.applied_to_train": "UNLOCALIZED: Train is now following this Schedule", "create.schedule.non_controlling_seat": "UNLOCALIZED: Conductor needs to sit in front of a Controls block", "create.schedule.remove_with_empty_hand": "UNLOCALIZED: Remove current Schedule with an Empty Hand", @@ -1508,6 +1507,8 @@ "create.train.relocate.valid": "UNLOCALIZED: Can relocate to here, Click to Confirm", "create.train.relocate.invalid": "UNLOCALIZED: Cannot relocate Train to here", "create.train.relocate.too_far": "UNLOCALIZED: Cannot relocate Train this far away", + "create.train.departing_from": "UNLOCALIZED: Departing from %1$s", + "create.train.arrived_at": "UNLOCALIZED: Arrived at %1$s", "create.track_signal.cannot_change_mode": "UNLOCALIZED: Unable to switch mode of this Signal", "create.track_signal.mode_change.entry_signal": "UNLOCALIZED: -> Allow passage if section unoccupied", 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 db84f3ca1..b4290ab40 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: 2221", + "_": "Missing Localizations: 2222", "_": "->------------------------] Game Elements [------------------------<-", @@ -1437,7 +1437,6 @@ "create.schedule.loop2": "UNLOCALIZED: when completed", "create.schedule.reset": "UNLOCALIZED: Reset Progress", "create.schedule.skip": "UNLOCALIZED: Skip current Stop", - "create.schedule.train_still_assembling": "UNLOCALIZED: Confirm Train Assembly in the Station UI first", "create.schedule.applied_to_train": "UNLOCALIZED: Train is now following this Schedule", "create.schedule.non_controlling_seat": "UNLOCALIZED: Conductor needs to sit in front of a Controls block", "create.schedule.remove_with_empty_hand": "UNLOCALIZED: Remove current Schedule with an Empty Hand", @@ -1508,6 +1507,8 @@ "create.train.relocate.valid": "UNLOCALIZED: Can relocate to here, Click to Confirm", "create.train.relocate.invalid": "UNLOCALIZED: Cannot relocate Train to here", "create.train.relocate.too_far": "UNLOCALIZED: Cannot relocate Train this far away", + "create.train.departing_from": "UNLOCALIZED: Departing from %1$s", + "create.train.arrived_at": "UNLOCALIZED: Arrived at %1$s", "create.track_signal.cannot_change_mode": "UNLOCALIZED: Unable to switch mode of this Signal", "create.track_signal.mode_change.entry_signal": "UNLOCALIZED: -> Allow passage if section unoccupied", 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 92796e670..bbddb92ca 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: 670", + "_": "Missing Localizations: 671", "_": "->------------------------] Game Elements [------------------------<-", @@ -1437,7 +1437,6 @@ "create.schedule.loop2": "UNLOCALIZED: when completed", "create.schedule.reset": "UNLOCALIZED: Reset Progress", "create.schedule.skip": "UNLOCALIZED: Skip current Stop", - "create.schedule.train_still_assembling": "UNLOCALIZED: Confirm Train Assembly in the Station UI first", "create.schedule.applied_to_train": "UNLOCALIZED: Train is now following this Schedule", "create.schedule.non_controlling_seat": "UNLOCALIZED: Conductor needs to sit in front of a Controls block", "create.schedule.remove_with_empty_hand": "UNLOCALIZED: Remove current Schedule with an Empty Hand", @@ -1508,6 +1507,8 @@ "create.train.relocate.valid": "UNLOCALIZED: Can relocate to here, Click to Confirm", "create.train.relocate.invalid": "UNLOCALIZED: Cannot relocate Train to here", "create.train.relocate.too_far": "UNLOCALIZED: Cannot relocate Train this far away", + "create.train.departing_from": "UNLOCALIZED: Departing from %1$s", + "create.train.arrived_at": "UNLOCALIZED: Arrived at %1$s", "create.track_signal.cannot_change_mode": "UNLOCALIZED: Unable to switch mode of this Signal", "create.track_signal.mode_change.entry_signal": "UNLOCALIZED: -> Allow passage if section unoccupied", 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 a3e60810e..918c4f4c0 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: 1165", + "_": "Missing Localizations: 1166", "_": "->------------------------] Game Elements [------------------------<-", @@ -1437,7 +1437,6 @@ "create.schedule.loop2": "UNLOCALIZED: when completed", "create.schedule.reset": "UNLOCALIZED: Reset Progress", "create.schedule.skip": "UNLOCALIZED: Skip current Stop", - "create.schedule.train_still_assembling": "UNLOCALIZED: Confirm Train Assembly in the Station UI first", "create.schedule.applied_to_train": "UNLOCALIZED: Train is now following this Schedule", "create.schedule.non_controlling_seat": "UNLOCALIZED: Conductor needs to sit in front of a Controls block", "create.schedule.remove_with_empty_hand": "UNLOCALIZED: Remove current Schedule with an Empty Hand", @@ -1508,6 +1507,8 @@ "create.train.relocate.valid": "UNLOCALIZED: Can relocate to here, Click to Confirm", "create.train.relocate.invalid": "UNLOCALIZED: Cannot relocate Train to here", "create.train.relocate.too_far": "UNLOCALIZED: Cannot relocate Train this far away", + "create.train.departing_from": "UNLOCALIZED: Departing from %1$s", + "create.train.arrived_at": "UNLOCALIZED: Arrived at %1$s", "create.track_signal.cannot_change_mode": "UNLOCALIZED: Unable to switch mode of this Signal", "create.track_signal.mode_change.entry_signal": "UNLOCALIZED: -> Allow passage if section unoccupied", 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 2d8e1e5db..b655f06e6 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: 1843", + "_": "Missing Localizations: 1844", "_": "->------------------------] Game Elements [------------------------<-", @@ -1437,7 +1437,6 @@ "create.schedule.loop2": "UNLOCALIZED: when completed", "create.schedule.reset": "UNLOCALIZED: Reset Progress", "create.schedule.skip": "UNLOCALIZED: Skip current Stop", - "create.schedule.train_still_assembling": "UNLOCALIZED: Confirm Train Assembly in the Station UI first", "create.schedule.applied_to_train": "UNLOCALIZED: Train is now following this Schedule", "create.schedule.non_controlling_seat": "UNLOCALIZED: Conductor needs to sit in front of a Controls block", "create.schedule.remove_with_empty_hand": "UNLOCALIZED: Remove current Schedule with an Empty Hand", @@ -1508,6 +1507,8 @@ "create.train.relocate.valid": "UNLOCALIZED: Can relocate to here, Click to Confirm", "create.train.relocate.invalid": "UNLOCALIZED: Cannot relocate Train to here", "create.train.relocate.too_far": "UNLOCALIZED: Cannot relocate Train this far away", + "create.train.departing_from": "UNLOCALIZED: Departing from %1$s", + "create.train.arrived_at": "UNLOCALIZED: Arrived at %1$s", "create.track_signal.cannot_change_mode": "UNLOCALIZED: Unable to switch mode of this Signal", "create.track_signal.mode_change.entry_signal": "UNLOCALIZED: -> Allow passage if section unoccupied", 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 9311d5709..2ac5b8760 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: 298", + "_": "Missing Localizations: 299", "_": "->------------------------] Game Elements [------------------------<-", @@ -1437,7 +1437,6 @@ "create.schedule.loop2": "UNLOCALIZED: when completed", "create.schedule.reset": "UNLOCALIZED: Reset Progress", "create.schedule.skip": "UNLOCALIZED: Skip current Stop", - "create.schedule.train_still_assembling": "UNLOCALIZED: Confirm Train Assembly in the Station UI first", "create.schedule.applied_to_train": "UNLOCALIZED: Train is now following this Schedule", "create.schedule.non_controlling_seat": "UNLOCALIZED: Conductor needs to sit in front of a Controls block", "create.schedule.remove_with_empty_hand": "UNLOCALIZED: Remove current Schedule with an Empty Hand", @@ -1508,6 +1507,8 @@ "create.train.relocate.valid": "UNLOCALIZED: Can relocate to here, Click to Confirm", "create.train.relocate.invalid": "UNLOCALIZED: Cannot relocate Train to here", "create.train.relocate.too_far": "UNLOCALIZED: Cannot relocate Train this far away", + "create.train.departing_from": "UNLOCALIZED: Departing from %1$s", + "create.train.arrived_at": "UNLOCALIZED: Arrived at %1$s", "create.track_signal.cannot_change_mode": "UNLOCALIZED: Unable to switch mode of this Signal", "create.track_signal.mode_change.entry_signal": "UNLOCALIZED: -> Allow passage if section unoccupied", 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 22e39021b..06c3786c7 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: 675", + "_": "Missing Localizations: 676", "_": "->------------------------] Game Elements [------------------------<-", @@ -1437,7 +1437,6 @@ "create.schedule.loop2": "UNLOCALIZED: when completed", "create.schedule.reset": "UNLOCALIZED: Reset Progress", "create.schedule.skip": "UNLOCALIZED: Skip current Stop", - "create.schedule.train_still_assembling": "UNLOCALIZED: Confirm Train Assembly in the Station UI first", "create.schedule.applied_to_train": "UNLOCALIZED: Train is now following this Schedule", "create.schedule.non_controlling_seat": "UNLOCALIZED: Conductor needs to sit in front of a Controls block", "create.schedule.remove_with_empty_hand": "UNLOCALIZED: Remove current Schedule with an Empty Hand", @@ -1508,6 +1507,8 @@ "create.train.relocate.valid": "UNLOCALIZED: Can relocate to here, Click to Confirm", "create.train.relocate.invalid": "UNLOCALIZED: Cannot relocate Train to here", "create.train.relocate.too_far": "UNLOCALIZED: Cannot relocate Train this far away", + "create.train.departing_from": "UNLOCALIZED: Departing from %1$s", + "create.train.arrived_at": "UNLOCALIZED: Arrived at %1$s", "create.track_signal.cannot_change_mode": "UNLOCALIZED: Unable to switch mode of this Signal", "create.track_signal.mode_change.entry_signal": "UNLOCALIZED: -> Allow passage if section unoccupied", 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 cb5a0a4fe..b026da709 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: 295", + "_": "Missing Localizations: 296", "_": "->------------------------] Game Elements [------------------------<-", @@ -1437,7 +1437,6 @@ "create.schedule.loop2": "UNLOCALIZED: when completed", "create.schedule.reset": "UNLOCALIZED: Reset Progress", "create.schedule.skip": "UNLOCALIZED: Skip current Stop", - "create.schedule.train_still_assembling": "UNLOCALIZED: Confirm Train Assembly in the Station UI first", "create.schedule.applied_to_train": "UNLOCALIZED: Train is now following this Schedule", "create.schedule.non_controlling_seat": "UNLOCALIZED: Conductor needs to sit in front of a Controls block", "create.schedule.remove_with_empty_hand": "UNLOCALIZED: Remove current Schedule with an Empty Hand", @@ -1508,6 +1507,8 @@ "create.train.relocate.valid": "UNLOCALIZED: Can relocate to here, Click to Confirm", "create.train.relocate.invalid": "UNLOCALIZED: Cannot relocate Train to here", "create.train.relocate.too_far": "UNLOCALIZED: Cannot relocate Train this far away", + "create.train.departing_from": "UNLOCALIZED: Departing from %1$s", + "create.train.arrived_at": "UNLOCALIZED: Arrived at %1$s", "create.track_signal.cannot_change_mode": "UNLOCALIZED: Unable to switch mode of this Signal", "create.track_signal.mode_change.entry_signal": "UNLOCALIZED: -> Allow passage if section unoccupied", 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 f0b455243..0042da3d5 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: 689", + "_": "Missing Localizations: 690", "_": "->------------------------] Game Elements [------------------------<-", @@ -1437,7 +1437,6 @@ "create.schedule.loop2": "UNLOCALIZED: when completed", "create.schedule.reset": "UNLOCALIZED: Reset Progress", "create.schedule.skip": "UNLOCALIZED: Skip current Stop", - "create.schedule.train_still_assembling": "UNLOCALIZED: Confirm Train Assembly in the Station UI first", "create.schedule.applied_to_train": "UNLOCALIZED: Train is now following this Schedule", "create.schedule.non_controlling_seat": "UNLOCALIZED: Conductor needs to sit in front of a Controls block", "create.schedule.remove_with_empty_hand": "UNLOCALIZED: Remove current Schedule with an Empty Hand", @@ -1508,6 +1507,8 @@ "create.train.relocate.valid": "UNLOCALIZED: Can relocate to here, Click to Confirm", "create.train.relocate.invalid": "UNLOCALIZED: Cannot relocate Train to here", "create.train.relocate.too_far": "UNLOCALIZED: Cannot relocate Train this far away", + "create.train.departing_from": "UNLOCALIZED: Departing from %1$s", + "create.train.arrived_at": "UNLOCALIZED: Arrived at %1$s", "create.track_signal.cannot_change_mode": "UNLOCALIZED: Unable to switch mode of this Signal", "create.track_signal.mode_change.entry_signal": "UNLOCALIZED: -> Allow passage if section unoccupied", diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/TrainHUD.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/TrainHUD.java index 4803ffed0..9efff2dae 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/TrainHUD.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/TrainHUD.java @@ -13,9 +13,11 @@ import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; import com.simibubi.create.foundation.utility.placement.PlacementHelpers; import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiComponent; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; +import net.minecraft.network.chat.Component; import net.minecraft.util.Mth; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; @@ -28,11 +30,25 @@ public class TrainHUD { static LerpedFloat displayedSpeed = LerpedFloat.linear(); static LerpedFloat displayedThrottle = LerpedFloat.linear(); + static LerpedFloat displayedPromptSize = LerpedFloat.linear(); static Double editedThrottle = null; static int hudPacketCooldown = 5; + public static Component currentPrompt; + public static boolean currentPromptShadow; + public static int promptKeepAlive = 0; + public static void tick() { + if (promptKeepAlive > 0) + promptKeepAlive--; + else + currentPrompt = null; + + displayedPromptSize.chase(currentPrompt != null ? Minecraft.getInstance().font.width(currentPrompt) + 17 : 0, + .5f, Chaser.EXP); + displayedPromptSize.tickChaser(); + Carriage carriage = getCarriage(); if (carriage == null) return; @@ -41,6 +57,7 @@ public class TrainHUD { double value = Math.abs(train.speed) / (train.maxSpeed() * AllConfigs.SERVER.trains.manualTrainSpeedModifier.getF()); value = Mth.clamp(value + 0.05f, 0, 1); + displayedSpeed.chase((int) (value * 18) / 18f, .5f, Chaser.EXP); displayedSpeed.tickChaser(); displayedThrottle.chase(editedThrottle != null ? editedThrottle : train.throttle, .75f, Chaser.EXP); @@ -96,6 +113,31 @@ public class TrainHUD { GuiComponent.blit(poseStack, 0, 0, 0, AllGuiTextures.TRAIN_HUD_SPEED.startX, AllGuiTextures.TRAIN_HUD_SPEED.startY, w, h, 256, 256); + int promptSize = (int) displayedPromptSize.getValue(partialTicks); + if (promptSize > 1) { + + poseStack.pushPose(); + poseStack.translate(promptSize / -2f + 91, -27, 100); + + AllGuiTextures.TRAIN_PROMPT_L.render(poseStack, -3, 0); + AllGuiTextures.TRAIN_PROMPT_R.render(poseStack, promptSize, 0); + GuiComponent.blit(poseStack, 0, 0, 0, AllGuiTextures.TRAIN_PROMPT.startX + (128 - promptSize / 2f), + AllGuiTextures.TRAIN_PROMPT.startY, promptSize, AllGuiTextures.TRAIN_PROMPT.height, 256, 256); + + poseStack.popPose(); + + Font font = Minecraft.getInstance().font; + if (currentPrompt != null && font.width(currentPrompt) < promptSize - 10) { + poseStack.pushPose(); + poseStack.translate(font.width(currentPrompt) / -2f + 82, -27, 100); + if (currentPromptShadow) + font.drawShadow(poseStack, currentPrompt, 9, 4, 0x544D45); + else + font.draw(poseStack, currentPrompt, 9, 4, 0x544D45); + poseStack.popPose(); + } + } + AllGuiTextures.TRAIN_HUD_DIRECTION.render(poseStack, 77, -20); w = (int) (AllGuiTextures.TRAIN_HUD_THROTTLE.width * (1 - displayedThrottle.getValue(partialTicks))); diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerInteractionBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerInteractionBehaviour.java index 8f02dc7b2..e5525fa2a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerInteractionBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerInteractionBehaviour.java @@ -82,11 +82,6 @@ public class BlazeBurnerInteractionBehaviour extends MovingInteractionBehaviour Schedule schedule = ScheduleItem.getSchedule(itemInHand); if (schedule == null) return false; - if (train.heldForAssembly) { - AllSoundEvents.DENY.playOnServer(player.level, player.blockPosition(), 1, 1); - player.displayClientMessage(Lang.translate("schedule.train_still_assembling"), true); - return true; - } if (schedule.entries.isEmpty()) { AllSoundEvents.DENY.playOnServer(player.level, player.blockPosition(), 1, 1); diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/RailwaySavedData.java b/src/main/java/com/simibubi/create/content/logistics/trains/RailwaySavedData.java index fc2b42097..a5b2c1fb3 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/RailwaySavedData.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/RailwaySavedData.java @@ -25,7 +25,7 @@ public class RailwaySavedData extends SavedData { @Override public CompoundTag save(CompoundTag nbt) { GlobalRailwayManager railways = Create.RAILWAYS; - Create.LOGGER.info("Saving Railway Information..."); +// Create.LOGGER.info("Saving Railway Information..."); DimensionPalette dimensions = new DimensionPalette(); nbt.put("RailGraphs", NBTHelper.writeCompoundList(railways.trackNetworks.values(), tg -> tg.write(dimensions))); nbt.put("SignalBlocks", NBTHelper.writeCompoundList(railways.signalEdgeGroups.values(), seg -> { @@ -43,7 +43,7 @@ public class RailwaySavedData extends SavedData { sd.trackNetworks = new HashMap<>(); sd.signalEdgeGroups = new HashMap<>(); sd.trains = new HashMap<>(); - Create.LOGGER.info("Loading Railway Information..."); +// Create.LOGGER.info("Loading Railway Information..."); DimensionPalette dimensions = DimensionPalette.read(nbt); NBTHelper.iterateCompoundList(nbt.getList("RailGraphs", Tag.TAG_COMPOUND), c -> { 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 a62be655f..a65f855ca 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 @@ -41,6 +41,7 @@ import net.minecraft.core.particles.ParticleTypes; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.KeybindComponent; +import net.minecraft.network.chat.MutableComponent; import net.minecraft.network.chat.TextComponent; import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataSerializers; @@ -482,10 +483,6 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity { return false; if (carriage.train.derailed) return false; - if (carriage.train.heldForAssembly) { - player.displayClientMessage(Lang.translate("schedule.train_still_assembling"), true); - return false; - } Train train = carriage.train; if (train.runtime.getSchedule() != null && !train.runtime.paused) @@ -558,8 +555,8 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity { boolean spaceDown = heldControls.contains(4); GlobalStation currentStation = carriage.train.getCurrentStation(); if (currentStation != null && spaceDown) { - player.displayClientMessage(new TextComponent(" Arrived at ").withStyle(ChatFormatting.GREEN) - .append(new TextComponent(currentStation.name).withStyle(ChatFormatting.WHITE)), true); + sendPrompt(player, Lang.translate("train.arrived_at", + new TextComponent(currentStation.name).withStyle(ChatFormatting.DARK_GREEN)), false); return true; } @@ -570,11 +567,12 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity { if (currentStation != null && targetSpeed != 0) { stationMessage = false; - player.displayClientMessage(new TextComponent(" Departing from ").withStyle(ChatFormatting.YELLOW) - .append(new TextComponent(currentStation.name).withStyle(ChatFormatting.WHITE)), true); + sendPrompt(player, Lang.translate("train.departing_from", + new TextComponent(currentStation.name).withStyle(ChatFormatting.DARK_GREEN)), false); } if (currentStation == null) { + Navigation nav = carriage.train.navigation; if (nav.destination != null) { if (!spaceDown) @@ -583,14 +581,18 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity { double f = (nav.distanceToDestination / navDistanceTotal); int progress = (int) (Mth.clamp(1 - ((1 - f) * (1 - f)), 0, 1) * 30); boolean arrived = progress == 0; - TextComponent whiteComponent = - new TextComponent(Strings.repeat("|", progress) + (arrived ? " ->" : " <-")); - TextComponent greenComponent = - new TextComponent((arrived ? "<- " : "-> ") + Strings.repeat("|", 30 - progress)); - int mixedColor = Color.mixColors(0x00_91EA44, 0x00_FFC244, progress / 30f); - int targetColor = arrived ? 0x00_91EA44 : 0x00_ffffff; - player.displayClientMessage(greenComponent.withStyle(st -> st.withColor(mixedColor)) - .append(whiteComponent.withStyle(st -> st.withColor(targetColor))), true); + TextComponent whiteComponent = new TextComponent(Strings.repeat("|", progress)); + TextComponent greenComponent = new TextComponent(Strings.repeat("|", 30 - progress)); + + int fromColor = 0x00_FFC244; + int toColor = 0x00_529915; + + int mixedColor = Color.mixColors(toColor, fromColor, progress / 30f); + int targetColor = arrived ? toColor : 0x00_544D45; + + MutableComponent component = greenComponent.withStyle(st -> st.withColor(mixedColor)) + .append(whiteComponent.withStyle(st -> st.withColor(targetColor))); + sendPrompt(player, component, true); carriage.train.manualTick = true; return true; } @@ -633,12 +635,17 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity { return true; } + private void sendPrompt(Player player, MutableComponent component, boolean shadow) { + if (player instanceof ServerPlayer sp) + AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> sp), new TrainPromptPacket(component, shadow)); + } + boolean stationMessage = false; private void displayApproachStationMessage(Player player, GlobalStation station) { - player.displayClientMessage( + sendPrompt(player, Lang.translate("contraption.controls.approach_station", new KeybindComponent("key.jump"), station.name), - true); + false); stationMessage = true; } 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 11c237443..686c14ab1 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 @@ -98,10 +98,6 @@ public class Train { public UUID currentStation; public boolean currentlyBackwards; - // considered for removal - @Deprecated - public boolean heldForAssembly; - public boolean doubleEnded; public List carriages; public List carriageSpacing; @@ -140,7 +136,6 @@ public class Train { navigation = new Navigation(this); runtime = new ScheduleRuntime(this); - heldForAssembly = false; migratingPoints = new ArrayList<>(); currentStation = null; manualSteer = SteerDirection.NONE; @@ -1074,7 +1069,6 @@ public class Train { if (currentStation != null) tag.putUUID("Station", currentStation); tag.putBoolean("Backwards", currentlyBackwards); - tag.putBoolean("StillAssembling", heldForAssembly); tag.putBoolean("Derailed", derailed); tag.putBoolean("UpdateSignals", updateSignalBlocks); tag.put("SignalBlocks", NBTHelper.writeCompoundList(occupiedSignalBlocks.entrySet(), e -> { @@ -1126,7 +1120,6 @@ public class Train { train.name = Component.Serializer.fromJson(tag.getString("Name")); train.currentStation = tag.contains("Station") ? tag.getUUID("Station") : null; train.currentlyBackwards = tag.getBoolean("Backwards"); - train.heldForAssembly = tag.getBoolean("StillAssembling"); train.derailed = tag.getBoolean("Derailed"); train.updateSignalBlocks = tag.getBoolean("UpdateSignals"); train.fuelTicks = tag.getInt("Fuel"); diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainPacket.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainPacket.java index bc3d40c5c..fc180a458 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainPacket.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainPacket.java @@ -60,7 +60,6 @@ public class TrainPacket extends SimplePacketBase { boolean doubleEnded = buffer.readBoolean(); train = new Train(trainId, owner, null, carriages, carriageSpacing, doubleEnded); - train.heldForAssembly = buffer.readBoolean(); train.name = Component.Serializer.fromJson(buffer.readUtf()); train.icon = TrainIconType.byId(buffer.readResourceLocation()); } @@ -94,7 +93,6 @@ public class TrainPacket extends SimplePacketBase { train.carriageSpacing.forEach(buffer::writeVarInt); buffer.writeBoolean(train.doubleEnded); - buffer.writeBoolean(train.heldForAssembly); buffer.writeUtf(Component.Serializer.toJson(train.name)); buffer.writeResourceLocation(train.icon.id); } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainPromptPacket.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainPromptPacket.java new file mode 100644 index 000000000..695a75392 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainPromptPacket.java @@ -0,0 +1,51 @@ +package com.simibubi.create.content.logistics.trains.entity; + +import java.util.function.Supplier; + +import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.TrainHUD; +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.chat.Component; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.fml.DistExecutor; +import net.minecraftforge.network.NetworkEvent.Context; + +public class TrainPromptPacket extends SimplePacketBase { + + private Component text; + private boolean shadow; + + public TrainPromptPacket(Component text, boolean shadow) { + this.text = text; + this.shadow = shadow; + } + + public TrainPromptPacket(FriendlyByteBuf buffer) { + text = buffer.readComponent(); + shadow = buffer.readBoolean(); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeComponent(text); + buffer.writeBoolean(shadow); + } + + @Override + public void handle(Supplier context) { + context.get() + .enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> this::apply)); + context.get() + .setPacketHandled(true); + } + + @OnlyIn(Dist.CLIENT) + public void apply() { + TrainHUD.currentPrompt = text; + TrainHUD.currentPromptShadow = shadow; + TrainHUD.promptKeepAlive = 30; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainRelocator.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainRelocator.java index 4bf644a29..cc66af449 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainRelocator.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainRelocator.java @@ -234,7 +234,6 @@ public class TrainRelocator { train.leaveStation(); train.derailed = false; - train.heldForAssembly = false; train.navigation.waitingForSignal = null; train.occupiedSignalBlocks.clear(); train.graph = graph; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/AssemblyScreen.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/AssemblyScreen.java index 44ef04baa..eefd1656d 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/AssemblyScreen.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/AssemblyScreen.java @@ -29,12 +29,10 @@ public class AssemblyScreen extends AbstractStationScreen { private List iconTypes; private ScrollInput iconTypeScroll; - private boolean assemblyCompleted; public AssemblyScreen(StationTileEntity te, GlobalStation station) { super(te, station); background = AllGuiTextures.STATION_ASSEMBLING; - assemblyCompleted = false; } @Override @@ -84,7 +82,6 @@ public class AssemblyScreen extends AbstractStationScreen { completeAssembly.active = false; completeAssembly.setToolTip(new TextComponent("Complete Assembly")); completeAssembly.withCallback(() -> { - assemblyCompleted = true; AllPackets.channel.sendToServer(StationEditPacket.configure(te.getBlockPos(), false, station.name)); minecraft.setScreen(new StationScreen(te, station)); }); @@ -106,7 +103,6 @@ public class AssemblyScreen extends AbstractStationScreen { toggleAssemblyButton.active = te.bogeyCount > 0 || train != null; if (train != null) { - assemblyCompleted = true; AllPackets.channel.sendToServer(StationEditPacket.configure(te.getBlockPos(), false, station.name)); minecraft.setScreen(new StationScreen(te, station)); for (Carriage carriage : train.carriages) @@ -115,33 +111,19 @@ public class AssemblyScreen extends AbstractStationScreen { } private void tickTrainDisplay() { - Train train = displayedTrain.get(); - Train imminentTrain = getImminent(); - - if (train == null) { - if (imminentTrain != null && !imminentTrain.heldForAssembly) { - displayedTrain = new WeakReference<>(imminentTrain); - completeAssembly.active = true; - quitAssembly.active = false; - iconTypeScroll.active = iconTypeScroll.visible = true; - toggleAssemblyButton.setToolTip(new TextComponent("Disassemble Train")); - toggleAssemblyButton.setIcon(AllGuiTextures.I_DISASSEMBLE_TRAIN); - toggleAssemblyButton.withCallback(() -> { - AllPackets.channel.sendToServer(StationEditPacket.tryDisassemble(te.getBlockPos())); - }); - } + if (getImminent() == null) { + displayedTrain = new WeakReference<>(null); + completeAssembly.active = false; + quitAssembly.active = true; + iconTypeScroll.active = iconTypeScroll.visible = false; + toggleAssemblyButton.setToolTip(new TextComponent("Assemble Train")); + toggleAssemblyButton.setIcon(AllGuiTextures.I_ASSEMBLE_TRAIN); + toggleAssemblyButton.withCallback(() -> { + AllPackets.channel.sendToServer(StationEditPacket.tryAssemble(te.getBlockPos())); + }); } else { - if (imminentTrain == null) { - displayedTrain = new WeakReference<>(null); - completeAssembly.active = false; - quitAssembly.active = true; - iconTypeScroll.active = iconTypeScroll.visible = false; - toggleAssemblyButton.setToolTip(new TextComponent("Assemble Train")); - toggleAssemblyButton.setIcon(AllGuiTextures.I_ASSEMBLE_TRAIN); - toggleAssemblyButton.withCallback(() -> { - AllPackets.channel.sendToServer(StationEditPacket.tryAssemble(te.getBlockPos())); - }); - } + AllPackets.channel.sendToServer(StationEditPacket.configure(te.getBlockPos(), false, station.name)); + minecraft.setScreen(new StationScreen(te, station)); } } @@ -242,7 +224,7 @@ public class AssemblyScreen extends AbstractStationScreen { if (train != null) { ResourceLocation iconId = iconTypes.get(iconTypeScroll.getState()); train.icon = TrainIconType.byId(iconId); - AllPackets.channel.sendToServer(new TrainEditPacket(train.id, "", !assemblyCompleted, iconId)); + AllPackets.channel.sendToServer(new TrainEditPacket(train.id, "", iconId)); } } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationEditPacket.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationEditPacket.java index 089370035..f596d3e8b 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationEditPacket.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationEditPacket.java @@ -113,9 +113,14 @@ public class StationEditPacket extends TileEntityConfigurationPacket> conditions = schedule.entries.get(currentEntry).conditions; - for (int i = 0; i < conditions.size(); i++) { - List list = conditions.get(i); - int progress = conditionProgress.get(i); - if (progress >= list.size()) - return TextComponent.EMPTY.copy(); + if (conditions.isEmpty() || conditionProgress.isEmpty() || conditionContext.isEmpty()) + return TextComponent.EMPTY.copy(); - CompoundTag tag = conditionContext.get(i); - ScheduleWaitCondition condition = list.get(progress); - return condition.getWaitingStatus(level, train, tag); - } + List list = conditions.get(0); + int progress = conditionProgress.get(0); + if (progress >= list.size()) + return TextComponent.EMPTY.copy(); - return TextComponent.EMPTY.copy(); + CompoundTag tag = conditionContext.get(0); + ScheduleWaitCondition condition = list.get(progress); + return condition.getWaitingStatus(level, train, tag); } } diff --git a/src/main/java/com/simibubi/create/foundation/gui/AllGuiTextures.java b/src/main/java/com/simibubi/create/foundation/gui/AllGuiTextures.java index 0b4f1b1dc..b594fdd07 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/AllGuiTextures.java +++ b/src/main/java/com/simibubi/create/foundation/gui/AllGuiTextures.java @@ -168,6 +168,9 @@ public enum AllGuiTextures implements ScreenElement { TRAIN_HUD_THROTTLE_POINTER("widgets", 0, 209, 6, 9), TRAIN_HUD_FRAME("widgets", 0, 200, 186, 7), TRAIN_HUD_DIRECTION("widgets", 77, 165, 28, 20), + TRAIN_PROMPT_L("widgets", 8, 209, 3, 16), + TRAIN_PROMPT_R("widgets", 11, 209, 3, 16), + TRAIN_PROMPT("widgets", 0, 230, 256, 16), // PlacementIndicator PLACEMENT_INDICATOR_SHEET("placement_indicator", 0, 0, 16, 256); diff --git a/src/main/java/com/simibubi/create/foundation/networking/AllPackets.java b/src/main/java/com/simibubi/create/foundation/networking/AllPackets.java index f216ae966..a8528275f 100644 --- a/src/main/java/com/simibubi/create/foundation/networking/AllPackets.java +++ b/src/main/java/com/simibubi/create/foundation/networking/AllPackets.java @@ -53,6 +53,7 @@ import com.simibubi.create.content.logistics.packet.FunnelFlapPacket; import com.simibubi.create.content.logistics.packet.TunnelFlapPacket; import com.simibubi.create.content.logistics.trains.TrackGraphSyncPacket; import com.simibubi.create.content.logistics.trains.entity.TrainPacket; +import com.simibubi.create.content.logistics.trains.entity.TrainPromptPacket; import com.simibubi.create.content.logistics.trains.entity.TrainRelocationPacket; import com.simibubi.create.content.logistics.trains.management.edgePoint.CurvedTrackSelectionPacket; import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalEdgeGroupPacket; @@ -171,6 +172,7 @@ public enum AllPackets { S_CONFIGURE_TRAIN(TrainEditReturnPacket.class, TrainEditReturnPacket::new, PLAY_TO_CLIENT), CONTROLS_ABORT(ControlsStopControllingPacket.class, ControlsStopControllingPacket::new, PLAY_TO_CLIENT), S_TRAIN_HUD(TrainHUDUpdatePacket.class, TrainHUDUpdatePacket::new, PLAY_TO_CLIENT), + S_TRAIN_PROMPT(TrainPromptPacket.class, TrainPromptPacket::new, PLAY_TO_CLIENT), ; diff --git a/src/main/resources/assets/create/lang/default/interface.json b/src/main/resources/assets/create/lang/default/interface.json index 77faa6663..9faa481d8 100644 --- a/src/main/resources/assets/create/lang/default/interface.json +++ b/src/main/resources/assets/create/lang/default/interface.json @@ -647,7 +647,6 @@ "create.schedule.loop2": "when completed", "create.schedule.reset": "Reset Progress", "create.schedule.skip": "Skip current Stop", - "create.schedule.train_still_assembling": "Confirm Train Assembly in the Station UI first", "create.schedule.applied_to_train": "Train is now following this Schedule", "create.schedule.non_controlling_seat": "Conductor needs to sit in front of a Controls block", "create.schedule.remove_with_empty_hand": "Remove current Schedule with an Empty Hand", @@ -718,6 +717,8 @@ "create.train.relocate.valid": "Can relocate to here, Click to Confirm", "create.train.relocate.invalid": "Cannot relocate Train to here", "create.train.relocate.too_far": "Cannot relocate Train this far away", + "create.train.departing_from": "Departing from %1$s", + "create.train.arrived_at": "Arrived at %1$s", "create.track_signal.cannot_change_mode": "Unable to switch mode of this Signal", "create.track_signal.mode_change.entry_signal": "-> Allow passage if section unoccupied", diff --git a/src/main/resources/assets/create/textures/gui/widgets.png b/src/main/resources/assets/create/textures/gui/widgets.png index 978685b26ffdb81b7fc0796190784d31d4ba9430..d2960eeb6ffec6821225268d5f3c9a06df815837 100644 GIT binary patch literal 9985 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 mD9FeEZJ`7lNu2mVG1&o literal 9720 zcma*Nbx<5n^e;NN1OkLWfCO3G-C0;z+#N!2Sb~Qj!DR^+2(q|)kOU6|3+@iVU4jR9 z7JYp0dsX+eiA} zH2(^yH<}lAXGqdZ{8^j8Oj5GJ77Gij-Q-|lBvHJSi<6}!Wy#9JHUT{0G#{E?I|Zy{ z?S`RX!|N436RgBcW@Kggi}Mj2-R_xQox9ztWr0(Zy-qWaeC1oNySW;DT(LI6$c^~J z<;C`2;CpD;Zy~wS5Red~mbUR$PtP$GW7S+X+gtQf2Ak%0+k$GAJJWe!ZamsqLS(APesYCd;{Mr7s* z0y)2}HBbXj>UK#)qSb@t;Orz3(*V1v-e!-?NXDL!T-$4kJ+{SsOSz8M*ao;S54b34 zKiHN#Uoi@yPLSh3lTc-El?gCW8B6WTJhWv*)vuz7MLy3cc*YR_e93G<(58=VuP;#l zot8<=8@I=tm(KkE{(weE_NqxP=e|qClB|&Tg|J$mR*nsRTP~e3u?!XB!ajX5pH_Z; zG>zZsn2HI;qA?k@bRQ<#eRP&?hTmRzF}Rc;Pab~Ki^Jj`(Nec}5L8s7dPIiux_qUw zLtJ!OLB%}-VNv+RaGHZ{DW%WpDwF$3k`IfE|EMVWUMx%gH(J21XM)F`YRQs#FZQgw zub>M5i)G7Tc8rM2t3WN7bv;yDzU3sO(M3IvbDEAj zo*iaM^HU^#6lRZA=u%D1P+_Fob$b`r|80M{+0egs)AEogOo5wuO>)eEt{oA)#L>6$ zGj4zuHY8XE`hId)C*!_YKefREAH=rD{$Y$QCqM%#M5)UrC07lH#WU;3#~TzI%8m=v;AK#lgZ7tI&AYoI>dSvf{O@-M8;A8+RTLm)E)e^8)|J#1}hAp|gXOl6oeY zbFCtY-wWqoSV?>_O`McyYT&%0=)BUL9)Yg&B-%rJG!_ycXm{3t9Xa+pIlD;_Osb)A z0MQ+G0%!z{Vv!+Sw@3N|(XfUj@Fdwu<2}J2YOSoSwBEh5iw=~b1xZUw^Mb)fvmMwO z!p=~W#xs*$@%@c6dyd!IzhreCH68Ln;j&Q1tidQHXvvHYuXU}Wt}&D(MQIyWDZMc# zRyUAkDzb^L^UZ3Lwt!;bFYBU`F0b7|$~%+`+VjphYPJ63oW5g3pILUb_&4{Ho6L$q zwsH^($v@!)8)o@0$O8V-tD{L1Cn5T+b`LLa?_cQX zFa7=%8ExlSR({iU07IVy+OSiWy*WC&hSB7*tPs7q-`z_lAQr=;tI|TN0uh z?-rQFl1$>h)*M*?fJ>B00=SXSP#16cs6o> zA7k-{MqpK}Hs`|ik6%JS-GOyMPI<*#|L&?goNR5)duc$j*ytnknS@YmQ1JiQG&IhJ zizkIabDyis`LSeRh~E7@GmnivIdKye|B-7@o$2mE3?=2`1_nFUK3dbp9-C+Ro3=3- zhZB!en9_xf9`L0iqLKF?H$rT5`sBe>@NngYg}o3(`u88k7Yay68(KYg zoF3KuZ<>p&%*@P&TnM404E~cle=65|nBv17nrKrEr&9(vOq0mVevE7x>PK$r|GI&7 z&R3S&oc8|^%$}Q`4iB%Gv}7~%9WS-j)zvM0lc0!gaCfa)O)dPpcRxpv>#In~DJH4} z3s*Z{?g%*7w(OKh=(eRvC(#S+dv9ct8Qk73HQ_6n8jR?UIRV(mIOeaU94Dl^r0L`q zcz@*S`~B`keeoP!C5?gXc+Y=?e%1BaDoPIfJ0d72pTFB*ufXf7C&!X%bzXJT{C<)H zPlooZ8pK1<=#?94UN+$DMy1B?$_c*Rubv&lCUha^QH8IqnOCC)TI)86kcb4E8i!(B zP|~d;ga*y?MOGP72NY-zF6g%^7Dh(YymoTK2n&d4Hh9g!@bPgij~P(%426-E_53~S zR%~SLojJ4Ch;xZk>kXy?^<*KG9w8Ki(@swXU{b7UYh%8Nk)cJtWl!Q_VfjNJ>j_q) zlkBrX*Y%;wga_Qt5cI`7JcNhoSDcfZ6VS^SutzM5-S>n;IA?PQ_C&+E2!pwWlU*#kb3=ogDo`yIDoJk>PL6(6y7lPU zH_k8>VgZ zTzJac%0MzS{>yJY^Fa7@w)a04nI{zCB<=xnv_II`D99e1g-C;3X>v)t)pVmrB*`$a zR|N5)pllwzS!%L=MY5ibDHgnbsN@N;3z7$uhV&~==*i6#2E2s&IR?X4#2Zy$@<1c+ z;JkAJ;3pZQ)}ZKa;d_f61Scc~Tt%6bup5lX(BQovFZ}{0CMx8Be?ff${hD;Nb~uR8 z3bwf+6kJU6SfNV@wbWyf-6THYG8yg$BBm30-Pl>f_S%%Q?+E$NO#ntamvp2f~ z9uvJBXK^V)f$eS)j@oJYd7Wy)_3II9k2O`fr%393cq++ttUOh$@o)D6kNw#b{X*E3`4-(rEOQsw+*drGF0jkNcuQN0l)^;_wiLs|JiSow+MqTE8ea#EMK4I zJ7>9t9-LnBH}$Ht?PI@YzB<+xRV6WkeUiPaR#6f=m9lV#+R>rxQ`D7swm~4#MeTM` zhnke&%9;5!Z<{zF^!*dw-rU@1_}u2uy$x&_!Hrz6CR+C$-9AivK!f(}^SGjRU>EN_ zKOpBBvDPzln^X-eyXQC)rv||eQy2l6A~FIqiE7l>C#0up(H^Md$SeYtH^ff^i}awS zFwZ|R#N*sVSv4Y-70WjGa`NRx3_A{}x~P)-3vQhm22D+FLcXZ*MipFrJYRxOnfpD) zH0}a6QHN}K<3QzM%+^}kf(J$+YIcxK^U#HFZ6{G?O7N4+6f4DvQ-ow_+)px{kP*fZ z7j?Ecz|Mv}NG;$*U;gWX2fsk2sT`+?%kW2;tn;IruboM-5r)~BKC`nfx>_dUd{6Z6 z@KA4<^yVca2HnjnOU|}`%XanKeCU(TFwo%hJ}uR#y%v9zDFD3rb|mK+d)L#h)8Gb* z6Su|KxF=&=3i$x{Z#45q&v>5kfFqQnBhY zdB2@63Eh%wN8=Vd%OH7cd;`up>wK1id;8-AIt-00dcKcF1N#uk2N1roTlsGlM%8?~ zgow@saxUeG&04mlhhsD&-{7kBEi&_?&ewk5dpcPp$-L{rLXYw9T(eYJ;$8-BiPv0^K}JF6WV0cnLphvVRx36Mo~?`LnY!O zjYtNEe6@7AF8=v*_pp!MIXM;9_ z0FG!tDM&X6gxv3{-_l5Yp)kZIl#B$L4+tfq+b=@jf;{U_)v)rkeIWPe6DbVEiV&9` z-?1kn$%>viYJcMo^q_0|=YoAnbJ)SOGG)z*n^R0LZniaaA9t zXGR7;I`llJnw)KOUslaPu{){y(ERQqX19+@?3Ux7Q_@-GXN9F5Ric);*d^+^%+Yh}@dS)Y8%tB=P$4V1X${ z;)Xd-zY{ybKIH^#PUaT88ui<}jdDuZpVJi@fo=)-->p**{+lXM{Vafb_O$4b(9?%i zEJ)j7q99OE^>%-s(qmE6PXBqwFUc`79-H-~T{&TkzLP9*pU|Ik?2&M7GLWoHI{+`r z_MdkMBze|`Fvc6ai0-U2-01W{y%aXV>v$KmYDWfFpy#c0T&O*bj*k9Zeg0Fr>zzbFSg?_M4>|k^Tly_y#A^rlRZyna zy6}wLyO+a#ca=?Vz6by@kOyHweI4PokHW2fx9%cdr?B$o=6hMyQ@xYw-MwR{*~+!& zWN>08HM49?_)E$yW25?OYYP*tIkaHW;F^Q zsucgUPyKifW^aS$pyeyqa2;J?&`Z+qkzaLeZHk?1-61)cs%I~uju)Pzfe4E(GN9&+ z$mmZBOFhSlR(5JO0o!>YH+AcWD#(w=sUD`Lifj*wusS4RIjK!jv5ymHkBZ>G&xv1D z#mn1OSoeEktAEO@Q!NT8^fX7SC{*!`pus<~gB%Hh0?n;CCFs2CR4Grf=<_MG;VAk zN{7~E{V=KzD2J34`-ldOz`&r+b}CDJ!@dZ;Z6&mq0^O|Zm-!{#zm_uvNZDX;fvG9|e= zMn?T#iufRfb*a;aY&a!Ygl_o3pMT5N2!3#P6d8FAlI;^toOkE5GgtY8Pm~ubpAC55 zS6Ohu_2DEwjvP@ffim+3StU(Pi(t|8!S(9zBYdw)nc(wOB?Qv@^#E}dK>-ySDhmPq#kAYkv=tvrGVCYlT7T<1%L!5YUu?{#s5}n|#U=3x2->2bNy<~B zM{EURP==z>sXZj{#tMbp1bAdUsB2>gEksI| z9b8IXuMVJDUzn5B9Uyxl^)UR8q><)ha7I);>Yg&Y+iWU;#g6f!YVC6;_G%TC%yV_% zZKb!Sq0hc1Vrx0W~1 zvZ_d^m7rn^0P`2MLdy$VSm8Pycn?*#n2uCK7syAe4r_7Gn!P{ESeLQcBw#9x=L}PV z*WE?QN7_t1)Oc&ZofpJ{U$SU8J*6TT9!o_Fu3L^yyI6oRz<&-Xm~# zcYnU)AJQ+WK%~k2gyrZC#vbQ?4K-(F!65H%YbhQ*G+>F0{ZynbFJLwQ0Wz_;Xk=GG z?Om7YH7y;u6B}w-Pwi%cN`~I$_)uP64&o@1%Kw_LD&2=_f!F4DwIrl=w@UF;rYKm`?k=3cWsqtE_lp1 zF{(!baqi0mUy?C5XRx@2Y>JPd$@16+WSlRI9`i+g%BIl|DSo^kruVGC@OdBp+UuGm;q=k0Z8VbA_KW4+XcCyQG_IgU&*7H)u zRt$N)AOE2Fo!%{2Gk8ldc;fhL1TEc65#s5EezWy_i#Q5v6-Bo4dnq+-;%BQXq!yO_ z0qEe4nW3-PI{7$b{>Ng<|5I;4SZw_z54?O(e8{A`cUduQ7Tt`Lta|-#GnLv`2jR3t zEg^m%DVcRzm`1cSnG{O?pRB^1X+*^i+-{F+(m|&k4-;B^37KwkImG_4GWsS6r#FBAUP#1IzUS5Bq@0aUSd3&f0TH@ZC47>{Qs z%^w_G>h7H+e1hiGHX8J~`ZDYE(yyV(x2s$Pm8p__sOETW#@R-@`vN&m%T}cJXk`1= zpB_t0{W{6uy91g16eyuMo8tiC&yVP}rNzGkZg2l>v^!BFl0913f{xq={>((Di`-Z@ z3c_)&BSQsVm%wJqCwMbRQ_B}qONqD*8n~zrwzN^9q!CyWuC7$0|EfO4Z$)zKv3WT1 zZyHCtEYUw@zN@{E*1LY5>S{vI!A7Ia7f@16O8^_BO#GBxBysZt!R+QX0JcHL*wZ|M zb5UquIMQg6eJ?_vq9g{qr{GGN>~ZeHwqtY1mP?}YlQKys(Qe4V^yzd!8ZEGK2mxV0z zJ$l&g2?@gT9_Fb4eT1m>k#vW7?DO~#6fS(WX+Ai(xArbHer=|0IV_yJUR}%1ZQL+X zM)cHv^^&7u^9N#&=9cJg=SNfT!yQa?xeRNk`a+|0-#^-$1{gei*fz{K_+q4qs|sM_ zon4xL1yHDtsFJ=!Q2p&yktBrFDs=K}v|Bs0Z8P%fHV}%*5S(;kw~;NDnHO$y>S3P27he^Bf^i-`;Q-SRq?sLdiO%#LB{;-8X73NnZrb zyv^(=1%5Lc6%|)f>@je-Dp$Db=b%*1s^p?J&LI{d~!UbE#j1J z_KVx04jAb_^{hf#l31=N8t4|xg%19WqoUwGIb647qXAV6uXiU!@eWRgv4zJxX0`XV zUGJd@s9MgXkWmEqE#EP7=?S`Jj zBjrft(?tJ5Xd!k|5_BZvVDhna5B{2XSK)H(qjz5<*cv>b(VrP|v>6@axA+Z7^Kj+Y zL1eMe_}-w^FLmQ*KCh@<+(u?yjFLA!(}B;3(!@VIVpAW#5*a1viwdsTv!YOXfrKP! zCsD{^b?A_a8Q26?t&*MDTUx7v zI5m1z5vCP!#{AR_x0Z`?e-Y}qkFsS(br<(>%0)G$R3})UdD8|5!aXh(X#elRBZ6)G88b?g0k+kPxM}VrA~fvVm2@_9dKem4xrM^|3|X)!SzH+e*x zJh?Y$H6&oNLp^4Xt?*$x;LBt5LRZoD4_2tN=kBPraOBxqfrV0y_&Xt zWize%T6*OTib{j&Dk8QdsuIab<>l^*MZ_)-=L=ez2j}Yi{DR7ko$veie&HDjgHneo z&oA*6C9>Hzz9tF`oRZjo%loN&B*fksRCLk!+2wA>gyXk5r&}wV?ynMhNLu1n(kE|| z`{9lAd0w1*zjMXj@0~9q^!h?v*Ci^9(P8w36xYmF?tDW$E93e3KfV zOF%ytD`EYfoO}f-LdKoC+~)J6QavU2fo5R$$1;!71cJLmj?)Kqhv`N0SRD<{H|k1_ zrsrW(jMnqF8ymSFY>lg-%K6Cd;SIN_C|~>B=_IxtP3``uKKqOSMni^O15(~awE-CoXEAB zgv7-Dh+0w{xsLHq*Y%}~O?uM~Moh0IJgX-;^er{DScyzE@U^}=%wJN4>m?6XtxzRh zEY$W*6F4RRS`bujYBCbX%kE-hRY8^r8Z#ww;Ja9i5*c_5UbqZWvi^GrhWW_D+?W|Q zPwEqb^T#z-Xr%vvGQ{RthW8+}hPBP=9jx4@b{e#Ht}gf6^f{1o633D#kgx|VyQX}F z-d?X_+D(A*L9_qT?F*L(y}7B0oxL5*%f2MT`ziGU*I7#yN_&~qu@^!Pv8My9;&n-{j}`e}@FFRax%BB06SGFvf7aTT zEV?W#-7HOiHML)G%TvaPO){fl;wal=h^L4>+m2S;8yNoSd?xt)#|K2j4~k(AIa>49 zNulzD!a`DkD1Q;38%l%U=D&T9M@ALECM+$QWN{|q73$FT(#e?_Mf!IfMPdX4jTc9W zdv#6f6grj242o~(7&yBk`F{|ljfZm0p_Lhjvs`s`%dA3m%uI3u*Owe; z@(Y&LL-Jce>nOg*1bg2KWdnjg;g7oxI0p^d=h@xguiIVf3QZ~3urresOueJqWFR}; zi<$o(u1>i(Nde;Oz063~6|%^6iuJTjd`H&m&j>q>+LGJM6d!4PWagT!)%ErEJqxSb zwU%daHdpX1j}o2ohidt~TcCtkg5hyDxEC6FCBnB|)VMZYpt4UcF8@CMhQ+5sTi&WR z;C=`pa<1oR+*B2~k;d(>3X+Fa=F59WyDP5aN3$7~L0nqBU#$I1nXYBc&O#BHaGrl7 z?bV+4yNjA5(F#B6-*>$9c_A%LI{z|f(U?}Yxiu8>9Z}AcLP4BF{qJGpv@91d*#8W? z+ZD~7DMB_9+)sZKaB5X{c^9w07ekuUWb?goEEn-+BDgKXp%gZS*I+Cj|qk& zOoAYJ0R-Y);6QDxtCZ2di)_#Z0de{%U50mJF#_gF1OGO=c*>-vh<92)8nN2zD>J`I z-W+DLg7rE7j>X!{wDB0IMjp!-SJ)@Oy=g=QT>ivSOz45jk*Mv()B9oH3Z1KiX*adB z$%Ra0m^b)w23gZKOQ&b0gRCQqK6)UBwO)*$2?{8)rXy^MW$ct*Z|WS0xg1}c2zVNZ zc&#D$^=cGlzv)faI3QrtC-XGko_NOAnOCeM=hQ+-Np0!s6Iu-_@bBeV*AQPHv8+6- zRgmk}LNwOcH3WC1-v@FnrbY}rs?1;kjP~mbcV<5?TkEoO_^Egd2ahF{8lx|iXrf+4 z_0C_JFxKvI5TB_{KVT8x;!5_e#eW!TU(n~aT?tw^&-}sR|NZg?=7&*BVAfbG-nQLz zk3n3unMVM4E?kj18NQiyzjbqTe>U)};ovw@kcEA@Y5BD29-VaK>=MOuVSm~EUgsVl zUU(3sKHid*IO2&2086(bo#ghd>cq9KO=>^1`V9d)*>n4ZTId^7Mkgn=VYc`{SHOa! z(7sjSCwk=ynR)WZBc=xvPU~~5#bSubmTQWm1lRy&hqz(-Kj#0^(_yfW3R>S2eBAJ!d{p8}MZ#A^YsUOf!y)f60KmP6;dM}0KM_;zY|40*!->Sx3mEKG0{~DGl#U07#&(UkTzn}k#TRIY@{;EgN z>lRk0Sl?0*?c7tbdz~)c$q(=a`vKo}a;~j$@BtRR>xCBd>(Bd=D9{M}yINcH!X7Z! zue}K(Er;Veaq$ooV)se_)QuW2k=z5u*mhp=cbZ!z+?x|-t=#^?d=ZgSNl zT@%gl_FFRlQMfLTdd%B%X%FW@=0pky>?_Wc$|~(!iI1-MNL-QSO;=tFhmL>6hc1mS zZ#XZE+36?zxZ;foE+NO8relDL)Edv~cAbc}A+eSUxbfCFBKyB24ECnwyI$^E-pk;Z zkS(57)5j@yuhrWChok~1O)xuX6~pYWBv@#((Jh!=ipDo08&M!@PQU7)SHlqe5-US2 z3Q_RfD1ePxS1=bHbeMB)) YdX|9oIpy!u-&%m8teQ+Y)a>*B1qw!R$N&HU