From 478d891a04a18ffb6f784d1a08b22a3354c434eb Mon Sep 17 00:00:00 2001 From: simibubi <31564874+simibubi@users.noreply.github.com> Date: Fri, 4 Feb 2022 05:15:53 +0100 Subject: [PATCH] Cut and Paste - Trains no longer disappear when a new train is created - Trains now crash into other trains - Fixed navigation complaining when schedule starts at current station - Fixed contraption interaction not iterating all potential colliders - Hovering tooltip for derailed trains - Trains can now be relocated using a wrench --- src/generated/resources/.cache/cache | 32 +- .../resources/assets/create/lang/en_us.json | 9 + .../assets/create/lang/unfinished/de_de.json | 11 +- .../assets/create/lang/unfinished/es_cl.json | 11 +- .../assets/create/lang/unfinished/es_es.json | 11 +- .../assets/create/lang/unfinished/fr_fr.json | 11 +- .../assets/create/lang/unfinished/it_it.json | 11 +- .../assets/create/lang/unfinished/ja_jp.json | 11 +- .../assets/create/lang/unfinished/ko_kr.json | 11 +- .../assets/create/lang/unfinished/nl_nl.json | 11 +- .../assets/create/lang/unfinished/pl_pl.json | 11 +- .../assets/create/lang/unfinished/pt_br.json | 11 +- .../assets/create/lang/unfinished/pt_pt.json | 11 +- .../assets/create/lang/unfinished/ru_ru.json | 11 +- .../assets/create/lang/unfinished/zh_cn.json | 11 +- .../assets/create/lang/unfinished/zh_tw.json | 11 +- .../data/create/advancements/aesthetics.json | 4 +- .../ContraptionHandlerClient.java | 116 ++++--- .../controls/ControlsRenderer.java | 8 + .../goggles/GoggleOverlayRenderer.java | 36 ++- .../logistics/trains/TrackGraphHelper.java | 89 +++++ .../logistics/trains/entity/Train.java | 98 +++++- .../trains/entity/TrainMigration.java | 3 +- .../trains/entity/TrainRelocator.java | 303 ++++++++++++++++++ .../logistics/trains/entity/TrainStatus.java | 4 + .../trains/entity/TravellingPoint.java | 2 +- .../trains/management/ScheduleRuntime.java | 5 +- .../trains/management/StationBlock.java | 6 + .../trains/management/StationTileEntity.java | 7 - .../management/TrackTargetingBehaviour.java | 78 +---- .../management/TrackTargetingBlockItem.java | 10 +- .../simibubi/create/events/ClientEvents.java | 2 + .../simibubi/create/events/InputEvents.java | 16 +- .../assets/create/lang/default/interface.json | 10 + 34 files changed, 810 insertions(+), 182 deletions(-) create mode 100644 src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphHelper.java create mode 100644 src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainRelocator.java diff --git a/src/generated/resources/.cache/cache b/src/generated/resources/.cache/cache index bc01cacaa..5248f581b 100644 --- a/src/generated/resources/.cache/cache +++ b/src/generated/resources/.cache/cache @@ -536,21 +536,21 @@ bf2b0310500213ff853c748c236eb5d01f61658e assets/create/blockstates/yellow_toolbo 7f39521b211441f5c3e06d60c5978cebe16cacfb assets/create/blockstates/zinc_block.json b7181bcd8182b2f17088e5aa881f374c9c65470c assets/create/blockstates/zinc_ore.json 9ffe5b3f8a39fa3c3a97a3c534bd82402177e82e assets/create/lang/en_ud.json -598112fe2d8be421bcf59e6a8556bef9d3f4e4a8 assets/create/lang/en_us.json -87bb8a47a6c898a99edd844bd3979e4100ca0a1e assets/create/lang/unfinished/de_de.json -daafd483d3956a6aacbc2be0048f26b6e3a52a70 assets/create/lang/unfinished/es_cl.json -4fe5d252e956a8ff0a76894137ee01e0303b7d6c assets/create/lang/unfinished/es_es.json -04e435c040a92e4929814517aebfcc8c92894afa assets/create/lang/unfinished/fr_fr.json -6729147b1f5400e514074ad49aad7c4b455925df assets/create/lang/unfinished/it_it.json -bab9ab05b5471ec5bdd156fd5f52c8201cbba177 assets/create/lang/unfinished/ja_jp.json -1807ffcdb033abb2fdab909bcfce3eff809028ee assets/create/lang/unfinished/ko_kr.json -b1f7fbadbc6bc9fda89e15d5ddd66e64af6b24bb assets/create/lang/unfinished/nl_nl.json -63f1c7fefca142c0635573460db1a151c04a38f4 assets/create/lang/unfinished/pl_pl.json -b24b3f5727d648589fede0773797829bbddef6c6 assets/create/lang/unfinished/pt_br.json -b0d0e10dee566e3ccb9323f2c3643ce3f731b8fb assets/create/lang/unfinished/pt_pt.json -1f86af12c35ed0396e213e51febc32b796a74830 assets/create/lang/unfinished/ru_ru.json -7e8a2165ad27a033ec2d85ec5e4818a3b97ec98e assets/create/lang/unfinished/zh_cn.json -1876f4adf2c478ad28fcb10b9ff0c9a56291f5b5 assets/create/lang/unfinished/zh_tw.json +a95bf9617620bb8b5fb82fe0e56e46bd336b278f assets/create/lang/en_us.json +b0115c492677dab858488cef73f2fd8eb6917868 assets/create/lang/unfinished/de_de.json +5165ae65abf3e3708a2546c4a90d1e73955358e0 assets/create/lang/unfinished/es_cl.json +052b77a7f53c2bff190db58d0c5cdd0fd46b0aa4 assets/create/lang/unfinished/es_es.json +33485bc349947338aef69f05cf23df3254c30b02 assets/create/lang/unfinished/fr_fr.json +f5effa80964b2a6afd5e4cc31de0658ab5f3ee4e assets/create/lang/unfinished/it_it.json +14db37211e03d9e8322d1f692c17325be405b4ff assets/create/lang/unfinished/ja_jp.json +fc1d89b9f72db1030d4dc11c73a58d8e9f20fc21 assets/create/lang/unfinished/ko_kr.json +3acc03de9c0e411d1d935464e8cd66c3745ad2d2 assets/create/lang/unfinished/nl_nl.json +23eaf81707d5d67816a3f035b9eee5b48e601624 assets/create/lang/unfinished/pl_pl.json +0a626a20150c4246ef5a956d7853424a95254222 assets/create/lang/unfinished/pt_br.json +4fd404306e795407325d17d9a68a3e6f5bbaf475 assets/create/lang/unfinished/pt_pt.json +74a3fec14772a0575debe0ec93f43d45cb556542 assets/create/lang/unfinished/ru_ru.json +f9f56931ea5cae9fecf7bf5f4f323cdbe1101f75 assets/create/lang/unfinished/zh_cn.json +1c5669a3109edbd448623a38e8b1c653f1a312c5 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 @@ -2135,7 +2135,7 @@ d080b1b25e5bc8baf5aee68691b08c7f12ece3b0 assets/create/models/item/windmill_bear a80fb25a0b655e76be986b5b49fcb0f03461a1ab assets/create/models/item/zinc_nugget.json b1689617190c05ef34bd18456b0c7ae09bb3210f assets/create/models/item/zinc_ore.json 5049f72c327a88f175f6f9425909e098fc711100 assets/create/sounds.json -0f1b4b980afba9bf2caf583b88e261bba8b10313 data/create/advancements/aesthetics.json +5d0cc4c0255dc241e61c173b31ddca70c88d08e4 data/create/advancements/aesthetics.json 613e64b44bed959da899fdd54c1cacb227fb33f2 data/create/advancements/andesite_alloy.json 81885c6bfb85792c88aaa7c9b70f58832945d31f data/create/advancements/andesite_casing.json 83c046bd200623933545c9e4326f782fb02c87fa data/create/advancements/arm_blaze_burner.json diff --git a/src/generated/resources/assets/create/lang/en_us.json b/src/generated/resources/assets/create/lang/en_us.json index f488404be..8b48e101f 100644 --- a/src/generated/resources/assets/create/lang/en_us.json +++ b/src/generated/resources/assets/create/lang/en_us.json @@ -1321,6 +1321,8 @@ "create.hint.empty_bearing": "_Right-click_ the bearing with an _empty_ _hand_ to _attach_ the structure you just built in front of it.", "create.hint.full_deployer.title": "Deployer Item Overflow", "create.hint.full_deployer": "It appears this _Deployer_ contains _excess_ _items_ that need to be _extracted._ Use a _hopper,_ _funnel_ or other means to free it from its overflow.", + "create.hint.derailed_train.title": "Derailed Train", + "create.hint.derailed_train": "It appears this _Train_ is no longer sitting on a connected track piece. _Right-Click_ using a _wrench_ in order to relocate it to a nearby track.", "create.gui.schedule.lmb_edit": "Left-Click to Edit", "create.gui.schedule.rmb_remove": "Right-Click to Remove", @@ -1404,6 +1406,13 @@ "create.track_target.too_far": "Targeted track is too far from here", "create.train.unnamed": "Unnamed Train", + "create.train.cannot_relocate_moving": "Cannot relocate a moving Train", + "create.train.relocate": "Click a Track to Relocate %1$s to. Sneak-Click to abort", + "create.train.relocate.abort": "Relocation aborted", + "create.train.relocate.success": "Relocation successful", + "create.train.relocate.valid": "Can be relocated here, Click to Confirm", + "create.train.relocate.invalid": "Cannot relocate Train to this Track", + "create.train.relocate.too_far": "Cannot relocate Train this far away", "create.gui.config.overlay1": "Hi :)", "create.gui.config.overlay2": "This is a sample overlay", 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 a46ca310a..0f7b6bc74 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: 1413", + "_": "Missing Localizations: 1422", "_": "->------------------------] Game Elements [------------------------<-", @@ -1322,6 +1322,8 @@ "create.hint.empty_bearing": "_Rechts-Klicke_ das Lager mit einer _leeren_ _Hand_ um die Struktur die du davor gebaut hast _anzubringen_.", "create.hint.full_deployer.title": "Einsatzgerät Gegenstand Überlauf", "create.hint.full_deployer": "Es scheint, dieses _Einsatzgerät_ enthält _überflüssige_ _Gegenstände_ die _extrahiert_ werden müssen. Nutze _Trichter_ oder anderes um ihn von seinem Überfluss zu befreien.", + "create.hint.derailed_train.title": "UNLOCALIZED: Derailed Train", + "create.hint.derailed_train": "UNLOCALIZED: It appears this _Train_ is no longer sitting on a connected track piece. _Right-Click_ using a _wrench_ in order to relocate it to a nearby track.", "create.gui.schedule.lmb_edit": "UNLOCALIZED: Left-Click to Edit", "create.gui.schedule.rmb_remove": "UNLOCALIZED: Right-Click to Remove", @@ -1405,6 +1407,13 @@ "create.track_target.too_far": "UNLOCALIZED: Targeted track is too far from here", "create.train.unnamed": "UNLOCALIZED: Unnamed Train", + "create.train.cannot_relocate_moving": "UNLOCALIZED: Cannot relocate a moving Train", + "create.train.relocate": "UNLOCALIZED: Click a Track to Relocate %1$s to. Sneak-Click to abort", + "create.train.relocate.abort": "UNLOCALIZED: Relocation aborted", + "create.train.relocate.success": "UNLOCALIZED: Relocation successful", + "create.train.relocate.valid": "UNLOCALIZED: Can be relocated here, Click to Confirm", + "create.train.relocate.invalid": "UNLOCALIZED: Cannot relocate Train to this Track", + "create.train.relocate.too_far": "UNLOCALIZED: Cannot relocate Train this far away", "create.gui.config.overlay1": "Hi :)", "create.gui.config.overlay2": "Dies ist ein Beispiel Overlay", 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 3a995dbf8..2e244fafb 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: 424", + "_": "Missing Localizations: 433", "_": "->------------------------] Game Elements [------------------------<-", @@ -1322,6 +1322,8 @@ "create.hint.empty_bearing": "Haz _Click-Derecho_ en el rodamiento con tu _mano_ _vacía_ para _unir_ la estructura que acabas de construir frente a él.", "create.hint.full_deployer.title": "Desbordamiento de objetos del Desplegador", "create.hint.full_deployer": "Parece que este _Desplegador_ contiene _objetos_ de _exceso_ que requieren ser _extraídos._ Usa una _tolva,_ _tolvogán_ u otros parecidos para librarlo del sobreflujo.", + "create.hint.derailed_train.title": "UNLOCALIZED: Derailed Train", + "create.hint.derailed_train": "UNLOCALIZED: It appears this _Train_ is no longer sitting on a connected track piece. _Right-Click_ using a _wrench_ in order to relocate it to a nearby track.", "create.gui.schedule.lmb_edit": "UNLOCALIZED: Left-Click to Edit", "create.gui.schedule.rmb_remove": "UNLOCALIZED: Right-Click to Remove", @@ -1405,6 +1407,13 @@ "create.track_target.too_far": "UNLOCALIZED: Targeted track is too far from here", "create.train.unnamed": "UNLOCALIZED: Unnamed Train", + "create.train.cannot_relocate_moving": "UNLOCALIZED: Cannot relocate a moving Train", + "create.train.relocate": "UNLOCALIZED: Click a Track to Relocate %1$s to. Sneak-Click to abort", + "create.train.relocate.abort": "UNLOCALIZED: Relocation aborted", + "create.train.relocate.success": "UNLOCALIZED: Relocation successful", + "create.train.relocate.valid": "UNLOCALIZED: Can be relocated here, Click to Confirm", + "create.train.relocate.invalid": "UNLOCALIZED: Cannot relocate Train to this Track", + "create.train.relocate.too_far": "UNLOCALIZED: Cannot relocate Train this far away", "create.gui.config.overlay1": "Hola :)", "create.gui.config.overlay2": "Este es un overlay de ejemplo", 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 72e9f60a7..482f7663d 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: 424", + "_": "Missing Localizations: 433", "_": "->------------------------] Game Elements [------------------------<-", @@ -1322,6 +1322,8 @@ "create.hint.empty_bearing": "Haz clic derecho sobre el rodamiento con la _mano vacía_ para _adjuntar_ la estructura que acabas de construir delante de él.", "create.hint.full_deployer.title": "Exceso de objetos en el desplegador", "create.hint.full_deployer": "Parece que este _desplegador_ contiene _exceso_ de objetos que necesitan ser _extraídos._ Usa una _tolva_, _embudo_ u otro medio para liberarlo de su excedente.", + "create.hint.derailed_train.title": "UNLOCALIZED: Derailed Train", + "create.hint.derailed_train": "UNLOCALIZED: It appears this _Train_ is no longer sitting on a connected track piece. _Right-Click_ using a _wrench_ in order to relocate it to a nearby track.", "create.gui.schedule.lmb_edit": "UNLOCALIZED: Left-Click to Edit", "create.gui.schedule.rmb_remove": "UNLOCALIZED: Right-Click to Remove", @@ -1405,6 +1407,13 @@ "create.track_target.too_far": "UNLOCALIZED: Targeted track is too far from here", "create.train.unnamed": "UNLOCALIZED: Unnamed Train", + "create.train.cannot_relocate_moving": "UNLOCALIZED: Cannot relocate a moving Train", + "create.train.relocate": "UNLOCALIZED: Click a Track to Relocate %1$s to. Sneak-Click to abort", + "create.train.relocate.abort": "UNLOCALIZED: Relocation aborted", + "create.train.relocate.success": "UNLOCALIZED: Relocation successful", + "create.train.relocate.valid": "UNLOCALIZED: Can be relocated here, Click to Confirm", + "create.train.relocate.invalid": "UNLOCALIZED: Cannot relocate Train to this Track", + "create.train.relocate.too_far": "UNLOCALIZED: Cannot relocate Train this far away", "create.gui.config.overlay1": "Hola :)", "create.gui.config.overlay2": "Esta es una muestra de la superposición", 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 f2d10559c..72276edf9 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: 1675", + "_": "Missing Localizations: 1684", "_": "->------------------------] Game Elements [------------------------<-", @@ -1322,6 +1322,8 @@ "create.hint.empty_bearing": "UNLOCALIZED: _Right-click_ the bearing with an _empty_ _hand_ to _attach_ the structure you just built in front of it.", "create.hint.full_deployer.title": "UNLOCALIZED: Deployer Item Overflow", "create.hint.full_deployer": "UNLOCALIZED: It appears this _Deployer_ contains _excess_ _items_ that need to be _extracted._ Use a _hopper,_ _funnel_ or other means to free it from its overflow.", + "create.hint.derailed_train.title": "UNLOCALIZED: Derailed Train", + "create.hint.derailed_train": "UNLOCALIZED: It appears this _Train_ is no longer sitting on a connected track piece. _Right-Click_ using a _wrench_ in order to relocate it to a nearby track.", "create.gui.schedule.lmb_edit": "UNLOCALIZED: Left-Click to Edit", "create.gui.schedule.rmb_remove": "UNLOCALIZED: Right-Click to Remove", @@ -1405,6 +1407,13 @@ "create.track_target.too_far": "UNLOCALIZED: Targeted track is too far from here", "create.train.unnamed": "UNLOCALIZED: Unnamed Train", + "create.train.cannot_relocate_moving": "UNLOCALIZED: Cannot relocate a moving Train", + "create.train.relocate": "UNLOCALIZED: Click a Track to Relocate %1$s to. Sneak-Click to abort", + "create.train.relocate.abort": "UNLOCALIZED: Relocation aborted", + "create.train.relocate.success": "UNLOCALIZED: Relocation successful", + "create.train.relocate.valid": "UNLOCALIZED: Can be relocated here, Click to Confirm", + "create.train.relocate.invalid": "UNLOCALIZED: Cannot relocate Train to this Track", + "create.train.relocate.too_far": "UNLOCALIZED: Cannot relocate Train this far away", "create.gui.config.overlay1": "UNLOCALIZED: Hi :)", "create.gui.config.overlay2": "UNLOCALIZED: This is a sample overlay", 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 d3c73d44d..f6047c3ed 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: 1364", + "_": "Missing Localizations: 1373", "_": "->------------------------] Game Elements [------------------------<-", @@ -1322,6 +1322,8 @@ "create.hint.empty_bearing": "_Clicca_ _col_ _destro_ il supporto con una _mano_ _vuota_ per _attaccarci_ la struttura che ci hai appena costruito davanti.", "create.hint.full_deployer.title": "Overflow di oggetti dell'installatore", "create.hint.full_deployer": "Sembra che questo _installatore_ contenga _oggetti_ _eccessivi_ che necessitano di essere _estratti_. Usa una _tramoggia_, un _imbuto_ o altro per liberarlo dall'overflow.", + "create.hint.derailed_train.title": "UNLOCALIZED: Derailed Train", + "create.hint.derailed_train": "UNLOCALIZED: It appears this _Train_ is no longer sitting on a connected track piece. _Right-Click_ using a _wrench_ in order to relocate it to a nearby track.", "create.gui.schedule.lmb_edit": "UNLOCALIZED: Left-Click to Edit", "create.gui.schedule.rmb_remove": "UNLOCALIZED: Right-Click to Remove", @@ -1405,6 +1407,13 @@ "create.track_target.too_far": "UNLOCALIZED: Targeted track is too far from here", "create.train.unnamed": "UNLOCALIZED: Unnamed Train", + "create.train.cannot_relocate_moving": "UNLOCALIZED: Cannot relocate a moving Train", + "create.train.relocate": "UNLOCALIZED: Click a Track to Relocate %1$s to. Sneak-Click to abort", + "create.train.relocate.abort": "UNLOCALIZED: Relocation aborted", + "create.train.relocate.success": "UNLOCALIZED: Relocation successful", + "create.train.relocate.valid": "UNLOCALIZED: Can be relocated here, Click to Confirm", + "create.train.relocate.invalid": "UNLOCALIZED: Cannot relocate Train to this Track", + "create.train.relocate.too_far": "UNLOCALIZED: Cannot relocate Train this far away", "create.gui.config.overlay1": "Ciao :)", "create.gui.config.overlay2": "Questo overlay è di esempio", 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 06fc14104..65c116869 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: 94", + "_": "Missing Localizations: 103", "_": "->------------------------] Game Elements [------------------------<-", @@ -1322,6 +1322,8 @@ "create.hint.empty_bearing": "_素手_でベアリングを_右クリック_して、その前に先ほど作った構造物を_接続_します。", "create.hint.full_deployer.title": "デプロイヤーのアイテムが溢れています", "create.hint.full_deployer": "この_デプロイヤー_には、_搬出_する必要がある余分なアイテムが含まれています。_ ホッパー_や_漏斗_などの手段を利用して、溢れないようにしてください。", + "create.hint.derailed_train.title": "UNLOCALIZED: Derailed Train", + "create.hint.derailed_train": "UNLOCALIZED: It appears this _Train_ is no longer sitting on a connected track piece. _Right-Click_ using a _wrench_ in order to relocate it to a nearby track.", "create.gui.schedule.lmb_edit": "UNLOCALIZED: Left-Click to Edit", "create.gui.schedule.rmb_remove": "UNLOCALIZED: Right-Click to Remove", @@ -1405,6 +1407,13 @@ "create.track_target.too_far": "UNLOCALIZED: Targeted track is too far from here", "create.train.unnamed": "UNLOCALIZED: Unnamed Train", + "create.train.cannot_relocate_moving": "UNLOCALIZED: Cannot relocate a moving Train", + "create.train.relocate": "UNLOCALIZED: Click a Track to Relocate %1$s to. Sneak-Click to abort", + "create.train.relocate.abort": "UNLOCALIZED: Relocation aborted", + "create.train.relocate.success": "UNLOCALIZED: Relocation successful", + "create.train.relocate.valid": "UNLOCALIZED: Can be relocated here, Click to Confirm", + "create.train.relocate.invalid": "UNLOCALIZED: Cannot relocate Train to this Track", + "create.train.relocate.too_far": "UNLOCALIZED: Cannot relocate Train this far away", "create.gui.config.overlay1": "やぁ(・∀・)", "create.gui.config.overlay2": "これはオーバーレイのサンプルです", 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 30d0924cc..675fc2150 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: 96", + "_": "Missing Localizations: 105", "_": "->------------------------] Game Elements [------------------------<-", @@ -1322,6 +1322,8 @@ "create.hint.empty_bearing": "_맨 손_으로 베어링을 _우클릭_하여 구조물을 _부착_하세요.", "create.hint.full_deployer.title": "기계 손 아이템 과적", "create.hint.full_deployer": "이 _기계 손_은 _배출_할 아이템을 가지고 있습니다. 호퍼 , 퍼널 등을 이용해 아이템을 빼내세요.", + "create.hint.derailed_train.title": "UNLOCALIZED: Derailed Train", + "create.hint.derailed_train": "UNLOCALIZED: It appears this _Train_ is no longer sitting on a connected track piece. _Right-Click_ using a _wrench_ in order to relocate it to a nearby track.", "create.gui.schedule.lmb_edit": "UNLOCALIZED: Left-Click to Edit", "create.gui.schedule.rmb_remove": "UNLOCALIZED: Right-Click to Remove", @@ -1405,6 +1407,13 @@ "create.track_target.too_far": "UNLOCALIZED: Targeted track is too far from here", "create.train.unnamed": "UNLOCALIZED: Unnamed Train", + "create.train.cannot_relocate_moving": "UNLOCALIZED: Cannot relocate a moving Train", + "create.train.relocate": "UNLOCALIZED: Click a Track to Relocate %1$s to. Sneak-Click to abort", + "create.train.relocate.abort": "UNLOCALIZED: Relocation aborted", + "create.train.relocate.success": "UNLOCALIZED: Relocation successful", + "create.train.relocate.valid": "UNLOCALIZED: Can be relocated here, Click to Confirm", + "create.train.relocate.invalid": "UNLOCALIZED: Cannot relocate Train to this Track", + "create.train.relocate.too_far": "UNLOCALIZED: Cannot relocate Train this far away", "create.gui.config.overlay1": "Hi :)", "create.gui.config.overlay2": "This is a sample overlay", 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 39fe925f1..5d717288c 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: 2028", + "_": "Missing Localizations: 2037", "_": "->------------------------] Game Elements [------------------------<-", @@ -1322,6 +1322,8 @@ "create.hint.empty_bearing": "UNLOCALIZED: _Right-click_ the bearing with an _empty_ _hand_ to _attach_ the structure you just built in front of it.", "create.hint.full_deployer.title": "UNLOCALIZED: Deployer Item Overflow", "create.hint.full_deployer": "UNLOCALIZED: It appears this _Deployer_ contains _excess_ _items_ that need to be _extracted._ Use a _hopper,_ _funnel_ or other means to free it from its overflow.", + "create.hint.derailed_train.title": "UNLOCALIZED: Derailed Train", + "create.hint.derailed_train": "UNLOCALIZED: It appears this _Train_ is no longer sitting on a connected track piece. _Right-Click_ using a _wrench_ in order to relocate it to a nearby track.", "create.gui.schedule.lmb_edit": "UNLOCALIZED: Left-Click to Edit", "create.gui.schedule.rmb_remove": "UNLOCALIZED: Right-Click to Remove", @@ -1405,6 +1407,13 @@ "create.track_target.too_far": "UNLOCALIZED: Targeted track is too far from here", "create.train.unnamed": "UNLOCALIZED: Unnamed Train", + "create.train.cannot_relocate_moving": "UNLOCALIZED: Cannot relocate a moving Train", + "create.train.relocate": "UNLOCALIZED: Click a Track to Relocate %1$s to. Sneak-Click to abort", + "create.train.relocate.abort": "UNLOCALIZED: Relocation aborted", + "create.train.relocate.success": "UNLOCALIZED: Relocation successful", + "create.train.relocate.valid": "UNLOCALIZED: Can be relocated here, Click to Confirm", + "create.train.relocate.invalid": "UNLOCALIZED: Cannot relocate Train to this Track", + "create.train.relocate.too_far": "UNLOCALIZED: Cannot relocate Train this far away", "create.gui.config.overlay1": "UNLOCALIZED: Hi :)", "create.gui.config.overlay2": "UNLOCALIZED: This is a sample overlay", 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 a3541a6fb..8cbb2a299 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: 463", + "_": "Missing Localizations: 472", "_": "->------------------------] Game Elements [------------------------<-", @@ -1322,6 +1322,8 @@ "create.hint.empty_bearing": "_Kliknij_ na łożysko _PPM_ pustą ręką, aby _przyczepić_ do niego strukturę zbudowaną z przodu.", "create.hint.full_deployer.title": "Nadmiar przedmiotów w aplikatorze", "create.hint.full_deployer": "Wygląda na to, że ten _aplikator_ zawiera _nadmiar_ _przedmiotów_, które muszą zostać _wyciągnięte_. Użyj _leji_, _lejków_ lub innych sposobów, aby uwolnić od przepełnienia.", + "create.hint.derailed_train.title": "UNLOCALIZED: Derailed Train", + "create.hint.derailed_train": "UNLOCALIZED: It appears this _Train_ is no longer sitting on a connected track piece. _Right-Click_ using a _wrench_ in order to relocate it to a nearby track.", "create.gui.schedule.lmb_edit": "UNLOCALIZED: Left-Click to Edit", "create.gui.schedule.rmb_remove": "UNLOCALIZED: Right-Click to Remove", @@ -1405,6 +1407,13 @@ "create.track_target.too_far": "UNLOCALIZED: Targeted track is too far from here", "create.train.unnamed": "UNLOCALIZED: Unnamed Train", + "create.train.cannot_relocate_moving": "UNLOCALIZED: Cannot relocate a moving Train", + "create.train.relocate": "UNLOCALIZED: Click a Track to Relocate %1$s to. Sneak-Click to abort", + "create.train.relocate.abort": "UNLOCALIZED: Relocation aborted", + "create.train.relocate.success": "UNLOCALIZED: Relocation successful", + "create.train.relocate.valid": "UNLOCALIZED: Can be relocated here, Click to Confirm", + "create.train.relocate.invalid": "UNLOCALIZED: Cannot relocate Train to this Track", + "create.train.relocate.too_far": "UNLOCALIZED: Cannot relocate Train this far away", "create.gui.config.overlay1": "Cześć :)", "create.gui.config.overlay2": "To jest przykładowa nakładka", 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 706378c6f..3dbc40c85 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: 1647", + "_": "Missing Localizations: 1656", "_": "->------------------------] Game Elements [------------------------<-", @@ -1322,6 +1322,8 @@ "create.hint.empty_bearing": "UNLOCALIZED: _Right-click_ the bearing with an _empty_ _hand_ to _attach_ the structure you just built in front of it.", "create.hint.full_deployer.title": "UNLOCALIZED: Deployer Item Overflow", "create.hint.full_deployer": "UNLOCALIZED: It appears this _Deployer_ contains _excess_ _items_ that need to be _extracted._ Use a _hopper,_ _funnel_ or other means to free it from its overflow.", + "create.hint.derailed_train.title": "UNLOCALIZED: Derailed Train", + "create.hint.derailed_train": "UNLOCALIZED: It appears this _Train_ is no longer sitting on a connected track piece. _Right-Click_ using a _wrench_ in order to relocate it to a nearby track.", "create.gui.schedule.lmb_edit": "UNLOCALIZED: Left-Click to Edit", "create.gui.schedule.rmb_remove": "UNLOCALIZED: Right-Click to Remove", @@ -1405,6 +1407,13 @@ "create.track_target.too_far": "UNLOCALIZED: Targeted track is too far from here", "create.train.unnamed": "UNLOCALIZED: Unnamed Train", + "create.train.cannot_relocate_moving": "UNLOCALIZED: Cannot relocate a moving Train", + "create.train.relocate": "UNLOCALIZED: Click a Track to Relocate %1$s to. Sneak-Click to abort", + "create.train.relocate.abort": "UNLOCALIZED: Relocation aborted", + "create.train.relocate.success": "UNLOCALIZED: Relocation successful", + "create.train.relocate.valid": "UNLOCALIZED: Can be relocated here, Click to Confirm", + "create.train.relocate.invalid": "UNLOCALIZED: Cannot relocate Train to this Track", + "create.train.relocate.too_far": "UNLOCALIZED: Cannot relocate Train this far away", "create.gui.config.overlay1": "UNLOCALIZED: Hi :)", "create.gui.config.overlay2": "UNLOCALIZED: This is a sample overlay", 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 06f7b3a12..5f1f58004 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: 1647", + "_": "Missing Localizations: 1656", "_": "->------------------------] Game Elements [------------------------<-", @@ -1322,6 +1322,8 @@ "create.hint.empty_bearing": "UNLOCALIZED: _Right-click_ the bearing with an _empty_ _hand_ to _attach_ the structure you just built in front of it.", "create.hint.full_deployer.title": "UNLOCALIZED: Deployer Item Overflow", "create.hint.full_deployer": "UNLOCALIZED: It appears this _Deployer_ contains _excess_ _items_ that need to be _extracted._ Use a _hopper,_ _funnel_ or other means to free it from its overflow.", + "create.hint.derailed_train.title": "UNLOCALIZED: Derailed Train", + "create.hint.derailed_train": "UNLOCALIZED: It appears this _Train_ is no longer sitting on a connected track piece. _Right-Click_ using a _wrench_ in order to relocate it to a nearby track.", "create.gui.schedule.lmb_edit": "UNLOCALIZED: Left-Click to Edit", "create.gui.schedule.rmb_remove": "UNLOCALIZED: Right-Click to Remove", @@ -1405,6 +1407,13 @@ "create.track_target.too_far": "UNLOCALIZED: Targeted track is too far from here", "create.train.unnamed": "UNLOCALIZED: Unnamed Train", + "create.train.cannot_relocate_moving": "UNLOCALIZED: Cannot relocate a moving Train", + "create.train.relocate": "UNLOCALIZED: Click a Track to Relocate %1$s to. Sneak-Click to abort", + "create.train.relocate.abort": "UNLOCALIZED: Relocation aborted", + "create.train.relocate.success": "UNLOCALIZED: Relocation successful", + "create.train.relocate.valid": "UNLOCALIZED: Can be relocated here, Click to Confirm", + "create.train.relocate.invalid": "UNLOCALIZED: Cannot relocate Train to this Track", + "create.train.relocate.too_far": "UNLOCALIZED: Cannot relocate Train this far away", "create.gui.config.overlay1": "UNLOCALIZED: Hi :)", "create.gui.config.overlay2": "UNLOCALIZED: This is a sample overlay", 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 8133d56e2..cfd0b760a 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: 468", + "_": "Missing Localizations: 477", "_": "->------------------------] Game Elements [------------------------<-", @@ -1322,6 +1322,8 @@ "create.hint.empty_bearing": "_Правый клик_ по подшипнику _пустой рукой_, чтобы _присоединить_ к нему структуру, которую вы только что построили перед ним.", "create.hint.full_deployer.title": "Переполнение автономного активатора", "create.hint.full_deployer": "Похоже, этот _автономный активатор_ содержит _лишние_ _предметы_, которые необходимо _извлечь_. Используйте _воронку_ или _другие способы_, чтобы освободить его от переполнения.", + "create.hint.derailed_train.title": "UNLOCALIZED: Derailed Train", + "create.hint.derailed_train": "UNLOCALIZED: It appears this _Train_ is no longer sitting on a connected track piece. _Right-Click_ using a _wrench_ in order to relocate it to a nearby track.", "create.gui.schedule.lmb_edit": "UNLOCALIZED: Left-Click to Edit", "create.gui.schedule.rmb_remove": "UNLOCALIZED: Right-Click to Remove", @@ -1405,6 +1407,13 @@ "create.track_target.too_far": "UNLOCALIZED: Targeted track is too far from here", "create.train.unnamed": "UNLOCALIZED: Unnamed Train", + "create.train.cannot_relocate_moving": "UNLOCALIZED: Cannot relocate a moving Train", + "create.train.relocate": "UNLOCALIZED: Click a Track to Relocate %1$s to. Sneak-Click to abort", + "create.train.relocate.abort": "UNLOCALIZED: Relocation aborted", + "create.train.relocate.success": "UNLOCALIZED: Relocation successful", + "create.train.relocate.valid": "UNLOCALIZED: Can be relocated here, Click to Confirm", + "create.train.relocate.invalid": "UNLOCALIZED: Cannot relocate Train to this Track", + "create.train.relocate.too_far": "UNLOCALIZED: Cannot relocate Train this far away", "create.gui.config.overlay1": "Привет :)", "create.gui.config.overlay2": "Это образец оверлея", 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 413534283..8976c2bed 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: 94", + "_": "Missing Localizations: 103", "_": "->------------------------] Game Elements [------------------------<-", @@ -1322,6 +1322,8 @@ "create.hint.empty_bearing": "_空手右击_轴承,可以将你新建造的结构_接到_轴承上。", "create.hint.full_deployer.title": "机械手物品溢出", "create.hint.full_deployer": "_机械手_包含_过剩的物品,_需要被_提取。你需要_使用_料斗,__漏斗_或其他方法将溢出释放出来。", + "create.hint.derailed_train.title": "UNLOCALIZED: Derailed Train", + "create.hint.derailed_train": "UNLOCALIZED: It appears this _Train_ is no longer sitting on a connected track piece. _Right-Click_ using a _wrench_ in order to relocate it to a nearby track.", "create.gui.schedule.lmb_edit": "UNLOCALIZED: Left-Click to Edit", "create.gui.schedule.rmb_remove": "UNLOCALIZED: Right-Click to Remove", @@ -1405,6 +1407,13 @@ "create.track_target.too_far": "UNLOCALIZED: Targeted track is too far from here", "create.train.unnamed": "UNLOCALIZED: Unnamed Train", + "create.train.cannot_relocate_moving": "UNLOCALIZED: Cannot relocate a moving Train", + "create.train.relocate": "UNLOCALIZED: Click a Track to Relocate %1$s to. Sneak-Click to abort", + "create.train.relocate.abort": "UNLOCALIZED: Relocation aborted", + "create.train.relocate.success": "UNLOCALIZED: Relocation successful", + "create.train.relocate.valid": "UNLOCALIZED: Can be relocated here, Click to Confirm", + "create.train.relocate.invalid": "UNLOCALIZED: Cannot relocate Train to this Track", + "create.train.relocate.too_far": "UNLOCALIZED: Cannot relocate Train this far away", "create.gui.config.overlay1": "Hi :)", "create.gui.config.overlay2": "这是一个实例层", 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 4638cdaa9..019a62550 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: 482", + "_": "Missing Localizations: 491", "_": "->------------------------] Game Elements [------------------------<-", @@ -1322,6 +1322,8 @@ "create.hint.empty_bearing": "_空手右鍵_軸承來_添加_你新建造的結構。", "create.hint.full_deployer.title": "機械手物品溢出", "create.hint.full_deployer": "_機械手_包含_過剩的物品_需要被_取出._使用漏斗_或其他方法將溢出解決。", + "create.hint.derailed_train.title": "UNLOCALIZED: Derailed Train", + "create.hint.derailed_train": "UNLOCALIZED: It appears this _Train_ is no longer sitting on a connected track piece. _Right-Click_ using a _wrench_ in order to relocate it to a nearby track.", "create.gui.schedule.lmb_edit": "UNLOCALIZED: Left-Click to Edit", "create.gui.schedule.rmb_remove": "UNLOCALIZED: Right-Click to Remove", @@ -1405,6 +1407,13 @@ "create.track_target.too_far": "UNLOCALIZED: Targeted track is too far from here", "create.train.unnamed": "UNLOCALIZED: Unnamed Train", + "create.train.cannot_relocate_moving": "UNLOCALIZED: Cannot relocate a moving Train", + "create.train.relocate": "UNLOCALIZED: Click a Track to Relocate %1$s to. Sneak-Click to abort", + "create.train.relocate.abort": "UNLOCALIZED: Relocation aborted", + "create.train.relocate.success": "UNLOCALIZED: Relocation successful", + "create.train.relocate.valid": "UNLOCALIZED: Can be relocated here, Click to Confirm", + "create.train.relocate.invalid": "UNLOCALIZED: Cannot relocate Train to this Track", + "create.train.relocate.too_far": "UNLOCALIZED: Cannot relocate Train this far away", "create.gui.config.overlay1": "嗨 :)", "create.gui.config.overlay2": "這是一個實例層", diff --git a/src/generated/resources/data/create/advancements/aesthetics.json b/src/generated/resources/data/create/advancements/aesthetics.json index d723cbe38..59a86f429 100644 --- a/src/generated/resources/data/create/advancements/aesthetics.json +++ b/src/generated/resources/data/create/advancements/aesthetics.json @@ -28,8 +28,8 @@ "trigger": "create:bracket_apply", "conditions": { "accepted_entries": [ - "create:cogwheel", - "create:large_cogwheel" + "create:large_cogwheel", + "create:cogwheel" ] } }, diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionHandlerClient.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionHandlerClient.java index 97d5cf406..7fe59d5c4 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionHandlerClient.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionHandlerClient.java @@ -1,10 +1,19 @@ package com.simibubi.create.content.contraptions.components.structureMovement; +import java.util.List; + +import javax.annotation.Nullable; + import org.apache.commons.lang3.mutable.MutableObject; +import com.simibubi.create.AllItems; import com.simibubi.create.content.contraptions.components.structureMovement.sync.ContraptionInteractionPacket; +import com.simibubi.create.content.logistics.trains.entity.CarriageContraptionEntity; +import com.simibubi.create.content.logistics.trains.entity.TrainRelocator; import com.simibubi.create.foundation.networking.AllPackets; +import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.RaycastHelper; +import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.RaycastHelper.PredicateTraceResult; import net.minecraft.client.Minecraft; @@ -14,6 +23,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; import net.minecraft.world.phys.AABB; @@ -61,6 +71,7 @@ public class ContraptionHandlerClient { public static void rightClickingOnContraptionsGetsHandledLocally(ClickInputEvent event) { Minecraft mc = Minecraft.getInstance(); LocalPlayer player = mc.player; + if (player == null) return; if (player.isPassenger()) @@ -69,53 +80,84 @@ public class ContraptionHandlerClient { return; if (!event.isUseItem()) return; - Vec3 origin = RaycastHelper.getTraceOrigin(player); - double reach = mc.gameMode.getPickRange(); - if (mc.hitResult != null && mc.hitResult.getLocation() != null) - reach = Math.min(mc.hitResult.getLocation() - .distanceTo(origin), reach); + Couple rayInputs = getRayInputs(player); + Vec3 origin = rayInputs.getFirst(); + Vec3 target = rayInputs.getSecond(); + AABB aabb = new AABB(origin, target); + List intersectingContraptions = + mc.level.getEntitiesOfClass(AbstractContraptionEntity.class, aabb); - Vec3 target = RaycastHelper.getTraceTarget(player, reach, origin); - for (AbstractContraptionEntity contraptionEntity : mc.level - .getEntitiesOfClass(AbstractContraptionEntity.class, new AABB(origin, target))) { + for (AbstractContraptionEntity contraptionEntity : intersectingContraptions) { + BlockHitResult rayTraceResult = rayTraceContraption(origin, target, contraptionEntity); + if (rayTraceResult == null) + continue; - Vec3 localOrigin = contraptionEntity.toLocalVector(origin, 1); - Vec3 localTarget = contraptionEntity.toLocalVector(target, 1); - Contraption contraption = contraptionEntity.getContraption(); - - MutableObject mutableResult = new MutableObject<>(); - PredicateTraceResult predicateResult = RaycastHelper.rayTraceUntil(localOrigin, localTarget, p -> { - StructureBlockInfo blockInfo = contraption.getBlocks() - .get(p); - if (blockInfo == null) - return false; - BlockState state = blockInfo.state; - VoxelShape raytraceShape = state.getShape(Minecraft.getInstance().level, BlockPos.ZERO.below()); - if (raytraceShape.isEmpty()) - return false; - BlockHitResult rayTrace = raytraceShape.clip(localOrigin, localTarget, p); - if (rayTrace != null) { - mutableResult.setValue(rayTrace); - return true; - } - return false; - }); - - if (predicateResult == null || predicateResult.missed()) - return; - - BlockHitResult rayTraceResult = mutableResult.getValue(); InteractionHand hand = event.getHand(); Direction face = rayTraceResult.getDirection(); BlockPos pos = rayTraceResult.getBlockPos(); - if (!contraptionEntity.handlePlayerInteraction(player, pos, face, hand)) - return; - AllPackets.channel.sendToServer(new ContraptionInteractionPacket(contraptionEntity, hand, pos, face)); + if (contraptionEntity.handlePlayerInteraction(player, pos, face, hand)) { + AllPackets.channel.sendToServer(new ContraptionInteractionPacket(contraptionEntity, hand, pos, face)); + } else if (handleSpecialInteractions(contraptionEntity, player, pos, face, hand)) { + } else + continue; + event.setCanceled(true); event.setSwingHand(false); } } + private static boolean handleSpecialInteractions(AbstractContraptionEntity contraptionEntity, Player player, + BlockPos localPos, Direction side, InteractionHand interactionHand) { + if (AllItems.WRENCH.isIn(player.getItemInHand(interactionHand)) + && contraptionEntity instanceof CarriageContraptionEntity car) + return TrainRelocator.carriageWrenched(car.toGlobalVector(VecHelper.getCenterOf(localPos), 1), car); + return false; + } + + @OnlyIn(Dist.CLIENT) + public static Couple getRayInputs(LocalPlayer player) { + Minecraft mc = Minecraft.getInstance(); + Vec3 origin = RaycastHelper.getTraceOrigin(player); + double reach = mc.gameMode.getPickRange(); + if (mc.hitResult != null && mc.hitResult.getLocation() != null) + reach = Math.min(mc.hitResult.getLocation() + .distanceTo(origin), reach); + Vec3 target = RaycastHelper.getTraceTarget(player, reach, origin); + return Couple.create(origin, target); + } + + @Nullable + public static BlockHitResult rayTraceContraption(Vec3 origin, Vec3 target, + AbstractContraptionEntity contraptionEntity) { + Vec3 localOrigin = contraptionEntity.toLocalVector(origin, 1); + Vec3 localTarget = contraptionEntity.toLocalVector(target, 1); + Contraption contraption = contraptionEntity.getContraption(); + + MutableObject mutableResult = new MutableObject<>(); + PredicateTraceResult predicateResult = RaycastHelper.rayTraceUntil(localOrigin, localTarget, p -> { + StructureBlockInfo blockInfo = contraption.getBlocks() + .get(p); + if (blockInfo == null) + return false; + BlockState state = blockInfo.state; + VoxelShape raytraceShape = state.getShape(Minecraft.getInstance().level, BlockPos.ZERO.below()); + if (raytraceShape.isEmpty()) + return false; + BlockHitResult rayTrace = raytraceShape.clip(localOrigin, localTarget, p); + if (rayTrace != null) { + mutableResult.setValue(rayTrace); + return true; + } + return false; + }); + + if (predicateResult == null || predicateResult.missed()) + return null; + + BlockHitResult rayTraceResult = mutableResult.getValue(); + return rayTraceResult; + } + } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsRenderer.java index c1906fe2f..d33d989f4 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsRenderer.java @@ -2,6 +2,7 @@ package com.simibubi.create.content.contraptions.components.structureMovement.in import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; import com.simibubi.create.AllBlockPartials; +import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; @@ -13,7 +14,9 @@ import com.simibubi.create.foundation.utility.Iterate; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.core.Direction; +import net.minecraft.util.Mth; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; public class ControlsRenderer { @@ -32,10 +35,15 @@ public class ControlsRenderer { .renderInto(matrices.getViewProjection(), buffer.getBuffer(RenderType.solid())); for (boolean first : Iterate.trueAndFalse) { + AbstractContraptionEntity entity = context.contraption.entity; + double motion = entity.position() + .distanceTo(new Vec3(entity.xo, entity.yo, entity.zo)); + float vAngle = (float) Mth.clamp(first ? motion * 45 : 0, -45, 45); SuperByteBuffer lever = CachedBufferer.partial(AllBlockPartials.TRAIN_CONTROLS_LEVER, state); lever.transform(matrices.getModel()) .centre() .rotateY(hAngle) + .rotateX(vAngle) .unCentre() .translate(first ? 0 : 6 / 16f, 0, 0) .light(matrices.getWorld(), ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld)) diff --git a/src/main/java/com/simibubi/create/content/contraptions/goggles/GoggleOverlayRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/goggles/GoggleOverlayRenderer.java index 118c292ec..c4c59fb8d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/goggles/GoggleOverlayRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/goggles/GoggleOverlayRenderer.java @@ -13,6 +13,7 @@ import com.simibubi.create.CreateClient; import com.simibubi.create.content.contraptions.components.structureMovement.IDisplayAssemblyExceptions; import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock; import com.simibubi.create.content.contraptions.components.structureMovement.piston.PistonExtensionPoleBlock; +import com.simibubi.create.content.logistics.trains.entity.TrainRelocator; import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.config.CClient; import com.simibubi.create.foundation.gui.RemovedGuiUtils; @@ -52,7 +53,8 @@ public class GoggleOverlayRenderer { public static int hoverTicks = 0; public static BlockPos lastHovered = null; - public static void renderOverlay(ForgeIngameGui gui, PoseStack poseStack, float partialTicks, int width, int height) { + public static void renderOverlay(ForgeIngameGui gui, PoseStack poseStack, float partialTicks, int width, + int height) { HitResult objectMouseOver = Minecraft.getInstance().hitResult; if (!(objectMouseOver instanceof BlockHitResult)) { @@ -76,6 +78,7 @@ public class GoggleOverlayRenderer { ItemStack headSlot = mc.player.getItemBySlot(EquipmentSlot.HEAD); BlockEntity te = world.getBlockEntity(pos); + int prevHoverTicks = hoverTicks; if (lastHovered == null || lastHovered.equals(pos)) hoverTicks++; else @@ -117,6 +120,11 @@ public class GoggleOverlayRenderer { } } + if (!hasHoveringInformation) + if (hasHoveringInformation = + hoverAddedInformation = TrainRelocator.addToTooltip(tooltip, mc.player.isShiftKeyDown())) + hoverTicks = prevHoverTicks + 1; + // break early if goggle or hover returned false when present if ((hasGoggleInformation && !goggleAddedInformation) && (hasHoveringInformation && !hoverAddedInformation)) return; @@ -173,15 +181,15 @@ public class GoggleOverlayRenderer { float fade = Mth.clamp((hoverTicks + partialTicks) / 12f, 0, 1); Boolean useCustom = cfg.overlayCustomColor.get(); - Color colorBackground = useCustom ? - new Color(cfg.overlayBackgroundColor.get()) : - Theme.c(Theme.Key.VANILLA_TOOLTIP_BACKGROUND).scaleAlpha(.75f); - Color colorBorderTop = useCustom ? - new Color(cfg.overlayBorderColorTop.get()) : - Theme.c(Theme.Key.VANILLA_TOOLTIP_BORDER, true).copy(); - Color colorBorderBot = useCustom ? - new Color(cfg.overlayBorderColorBot.get()) : - Theme.c(Theme.Key.VANILLA_TOOLTIP_BORDER, false).copy(); + Color colorBackground = useCustom ? new Color(cfg.overlayBackgroundColor.get()) + : Theme.c(Theme.Key.VANILLA_TOOLTIP_BACKGROUND) + .scaleAlpha(.75f); + Color colorBorderTop = useCustom ? new Color(cfg.overlayBorderColorTop.get()) + : Theme.c(Theme.Key.VANILLA_TOOLTIP_BORDER, true) + .copy(); + Color colorBorderBot = useCustom ? new Color(cfg.overlayBorderColorBot.get()) + : Theme.c(Theme.Key.VANILLA_TOOLTIP_BORDER, false) + .copy(); if (fade < 1) { poseStack.translate((1 - fade) * Math.signum(cfg.overlayOffsetX.get() + .5f) * 4, 0, 0); @@ -190,8 +198,8 @@ public class GoggleOverlayRenderer { colorBorderBot.scaleAlpha(fade); } - RemovedGuiUtils.drawHoveringText(poseStack, tooltip, posX, posY, width, height, -1, - colorBackground.getRGB(), colorBorderTop.getRGB(), colorBorderBot.getRGB(), mc.font); + RemovedGuiUtils.drawHoveringText(poseStack, tooltip, posX, posY, width, height, -1, colorBackground.getRGB(), + colorBorderTop.getRGB(), colorBorderBot.getRGB(), mc.font); ItemStack item = AllItems.GOGGLES.asStack(); GuiGameElement.of(item) @@ -201,8 +209,8 @@ public class GoggleOverlayRenderer { } /** - * Use this method to add custom entry points to the goggles overlay, e.g. custom - * armor, handheld alternatives, etc. + * Use this method to add custom entry points to the goggles overlay, e.g. + * custom armor, handheld alternatives, etc. */ public static void registerCustomGoggleCondition(Supplier condition) { customGogglePredicates.add(condition); diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphHelper.java b/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphHelper.java new file mode 100644 index 000000000..d716058c4 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphHelper.java @@ -0,0 +1,89 @@ +package com.simibubi.create.content.logistics.trains; + +import java.util.List; + +import com.simibubi.create.Create; +import com.simibubi.create.content.logistics.trains.TrackNodeLocation.DiscoveredLocation; +import com.simibubi.create.content.logistics.trains.management.GraphLocation; +import com.simibubi.create.foundation.utility.Couple; +import com.simibubi.create.foundation.utility.Pair; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction.AxisDirection; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class TrackGraphHelper { + + public static GraphLocation getGraphLocationAt(Level level, BlockPos pos, AxisDirection targetDirection) { + BlockState trackBlockState = level.getBlockState(pos); + if (!(trackBlockState.getBlock()instanceof ITrackBlock track)) + return null; + + Vec3 axis = track.getTrackAxis(level, pos, trackBlockState) + .scale(targetDirection.getStep()); + double length = axis.length(); + + List> ends = + TrackPropagator.getEnds(level, pos, trackBlockState, null, true); + + TrackGraph graph = null; + TrackNode frontNode = null; + TrackNode backNode = null; + double position = 0; + + for (Pair pair : ends) { + DiscoveredLocation current = pair.getSecond(); + BlockPos currentPos = pair.getFirst(); + Vec3 offset = Vec3.atLowerCornerOf(currentPos.subtract(pos)); + boolean forward = offset.distanceToSqr(axis.scale(-1)) < 1 / 4096f; + boolean backwards = offset.distanceToSqr(axis) < 1 / 4096f; + + if (!forward && !backwards) + continue; + + for (int i = 0; i < 32; i++) { + DiscoveredLocation loc = current; + List> list = + TrackPropagator.getEnds(level, currentPos, level.getBlockState(currentPos), current, true); + if (!list.isEmpty()) { + currentPos = list.get(0) + .getFirst(); + current = list.get(0) + .getSecond(); + } + + if (graph == null) + graph = Create.RAILWAYS.getGraph(level, loc); + if (graph == null) + continue; + TrackNode node = graph.locateNode(loc); + if (node == null) + continue; + if (forward) + frontNode = node; + if (backwards) { + backNode = node; + position = (i + .5) * length; + } + break; + } + } + + if (frontNode == null || backNode == null) + return null; + + GraphLocation graphLocation = new GraphLocation(); + graphLocation.edge = Couple.create(backNode.getLocation(), frontNode.getLocation()); + graphLocation.position = position; + graphLocation.graph = graph; + return graphLocation; + } + + public static boolean getTrackDirectionByLookVec(Vec3 lookAngle, Level level, BlockPos pos, BlockState state, + ITrackBlock track) { + return lookAngle.dot(track.getTrackAxis(level, pos, state)) < 0; + } + +} 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 d1542afad..73c15c9a1 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 @@ -25,13 +25,17 @@ import com.simibubi.create.content.logistics.trains.management.GlobalStation; import com.simibubi.create.content.logistics.trains.management.GraphLocation; import com.simibubi.create.content.logistics.trains.management.ScheduleRuntime; import com.simibubi.create.content.logistics.trains.management.ScheduleRuntime.State; +import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; import net.minecraft.network.chat.Component; import net.minecraft.util.Mth; import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.level.Explosion.BlockInteraction; import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec3; @@ -91,7 +95,7 @@ public class Train { public void tick(Level level) { status.tick(level); - + if (graph == null) { if (!migratingPoints.isEmpty()) reattachToTracks(level); @@ -107,6 +111,12 @@ public class Train { speed = 0; } + if (derailed) { + speed /= 3f; + if (Mth.equal(speed, 0)) + speed = 0; + } + double distance = speed; Carriage previousCarriage = null; @@ -143,8 +153,10 @@ public class Train { double actualDistance = carriage.travel(level, graph, distance + leadingStress + trailingStress, control); blocked |= carriage.blocked; - if (i == 0) + if (i == 0) { distance = actualDistance; + collideWithOtherTrains(level, carriage); + } previous = carriage.getTrailingPoint(); } @@ -164,6 +176,86 @@ public class Train { } } + private void collideWithOtherTrains(Level level, Carriage carriage) { + if (derailed) + return; + Collision: for (Train train : Create.RAILWAYS.trains.values()) { + if (train == this) + continue; + Vec3 start = carriage.getLeadingPoint() + .getPosition(); + Vec3 end = carriage.getTrailingPoint() + .getPosition(); + Vec3 diff = end.subtract(start); + Vec3 lastPoint = null; + + for (Carriage otherCarriage : train.carriages) { + for (boolean betweenBits : Iterate.trueAndFalse) { + if (betweenBits && lastPoint == null) + continue; + + Vec3 start2 = otherCarriage.getLeadingPoint() + .getPosition(); + Vec3 end2 = otherCarriage.getTrailingPoint() + .getPosition(); + if (betweenBits) { + end2 = start2; + start2 = lastPoint; + } + + lastPoint = end2; + + if ((end.y < end2.y - 3 || end2.y < end.y - 3) + && (start.y < start2.y - 3 || start2.y < start.y - 3)) + continue; + + Vec3 diff2 = end2.subtract(start2); + Vec3 normedDiff = diff.normalize(); + Vec3 normedDiff2 = diff2.normalize(); + double[] intersect = VecHelper.intersect(start, start2, normedDiff, normedDiff2, Axis.Y); + if (intersect == null) { + Vec3 intersectSphere = VecHelper.intersectSphere(start2, normedDiff2, start, .125f); + if (intersectSphere == null) + continue; + if (!Mth.equal(normedDiff2.dot(intersectSphere.subtract(start2) + .normalize()), 1)) + continue; + intersect = new double[2]; + intersect[0] = intersectSphere.distanceTo(start) - .125; + intersect[1] = intersectSphere.distanceTo(start2) - .125; + } + if (intersect[0] > diff.length()) + continue; + if (intersect[1] > diff2.length()) + continue; + if (intersect[0] < 0) + continue; + if (intersect[1] < 0) + continue; + + double combinedSpeed = speed + train.speed; + if (combinedSpeed > .2f) { + Vec3 v = start.add(normedDiff.scale(intersect[0])); + level.explode(null, v.x, v.y, v.z, (float) Math.min(3 * combinedSpeed, 5), + BlockInteraction.NONE); + } + crash(); + train.crash(); + break Collision; + } + } + } + } + + public void crash() { + navigation.cancelNavigation(); + if (derailed) + return; + speed = -Mth.clamp(speed, -.5, .5); + derailed = true; + status.crash(); + } + public boolean disassemble(Direction assemblyDirection, BlockPos pos) { for (Carriage carriage : carriages) { CarriageContraptionEntity entity = carriage.entity.get(); @@ -219,7 +311,7 @@ public class Train { } - private void forEachTravellingPoint(Consumer callback) { + public void forEachTravellingPoint(Consumer callback) { for (Carriage c : carriages) { c.leadingBogey().points.forEach(callback::accept); if (c.isOnTwoBogeys()) diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainMigration.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainMigration.java index db9d84e0b..91f5e903f 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainMigration.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainMigration.java @@ -13,7 +13,8 @@ import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.util.Mth; import net.minecraft.world.phys.Vec3; -class TrainMigration { +public class TrainMigration { + Couple locations; double positionOnOldEdge; boolean curve; 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 new file mode 100644 index 000000000..e67b42f52 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainRelocator.java @@ -0,0 +1,303 @@ +package com.simibubi.create.content.logistics.trains.entity; + +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.function.Consumer; + +import javax.annotation.Nullable; + +import com.simibubi.create.AllItems; +import com.simibubi.create.Create; +import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionHandlerClient; +import com.simibubi.create.content.logistics.trains.ITrackBlock; +import com.simibubi.create.content.logistics.trains.TrackEdge; +import com.simibubi.create.content.logistics.trains.TrackGraph; +import com.simibubi.create.content.logistics.trains.TrackGraphHelper; +import com.simibubi.create.content.logistics.trains.TrackNode; +import com.simibubi.create.content.logistics.trains.entity.TravellingPoint.ITrackSelector; +import com.simibubi.create.content.logistics.trains.entity.TravellingPoint.SteerDirection; +import com.simibubi.create.content.logistics.trains.management.GraphLocation; +import com.simibubi.create.foundation.item.TooltipHelper; +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.Minecraft; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction.AxisDirection; +import net.minecraft.network.chat.Component; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.HitResult; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.client.event.InputEvent.ClickInputEvent; + +public class TrainRelocator { + + static WeakReference hoveredEntity = new WeakReference<>(null); + static UUID relocatingTrain; + static Vec3 relocatingOrigin; + + static BlockPos lastHoveredPos; + static Boolean lastHoveredResult; + + public static void onClicked(ClickInputEvent event) { + if (relocatingTrain == null) + return; + + Minecraft mc = Minecraft.getInstance(); + LocalPlayer player = mc.player; + if (player == null) + return; + + if (!player.position() + .closerThan(relocatingOrigin, 24) || player.isSteppingCarefully()) { + relocatingTrain = null; + player.displayClientMessage(Lang.translate("train.relocate.abort") + .withStyle(ChatFormatting.RED), true); + return; + } + + if (player.isPassenger()) + return; + if (mc.level == null) + return; + Train relocating = getRelocating(); + if (relocating != null) { + Boolean relocate = relocateClient(relocating, false); // TODO send packet + if (relocate != null && relocate.booleanValue()) { + relocatingTrain = null; + player.displayClientMessage(Lang.translate("train.relocate.success") + .withStyle(ChatFormatting.GREEN), true); + } + if (relocate != null) + event.setCanceled(true); + } + } + + @Nullable + public static Boolean relocateClient(Train relocating, boolean simulate) { + Minecraft mc = Minecraft.getInstance(); + HitResult hitResult = mc.hitResult; + if (!(hitResult instanceof BlockHitResult blockhit)) + return null; + BlockPos blockPos = blockhit.getBlockPos(); + + if (simulate) { + if (lastHoveredPos != null && lastHoveredPos.equals(blockPos)) + return lastHoveredResult; + lastHoveredPos = blockPos; + } + + BlockState blockState = mc.level.getBlockState(blockPos); + if (!(blockState.getBlock()instanceof ITrackBlock track)) + return lastHoveredResult = null; + return lastHoveredResult = relocate(relocating, mc.player, blockPos, simulate); + } + + public static boolean relocate(Train train, Player player, BlockPos pos, boolean simulate) { + Vec3 lookAngle = player.getLookAngle(); + Level level = player.getLevel(); + BlockState blockState = level.getBlockState(pos); + if (!(blockState.getBlock()instanceof ITrackBlock track)) + return false; + boolean front = TrackGraphHelper.getTrackDirectionByLookVec(lookAngle, level, pos, blockState, track); + GraphLocation graphLocation = + TrackGraphHelper.getGraphLocationAt(level, pos, front ? AxisDirection.POSITIVE : AxisDirection.NEGATIVE); + + if (graphLocation == null) + return false; + + TrackGraph graph = graphLocation.graph; + TrackNode node1 = graph.locateNode(graphLocation.edge.getFirst()); + TrackNode node2 = graph.locateNode(graphLocation.edge.getSecond()); + TrackEdge edge = graph.getConnectionsFrom(node1) + .get(node2); + if (edge == null) + return false; + + TravellingPoint probe = new TravellingPoint(node1, node2, edge, graphLocation.position); + List, Double>> recordedLocations = new ArrayList<>(); + Consumer recorder = + tp -> recordedLocations.add(Pair.of(Couple.create(tp.node1, tp.node2), tp.position)); + recorder.accept(probe); + + double lastWheelOffset = 0; + ITrackSelector steer = probe.steer(SteerDirection.NONE, track.getUpNormal(level, pos, blockState)); + for (int i = 0; i < train.carriages.size(); i++) { + int index = train.carriages.size() - i - 1; + Carriage carriage = train.carriages.get(index); + double trailSpacing = carriage.trailingBogey().type.getWheelPointSpacing(); + if (i > 0) { + probe.travel(graph, train.carriageSpacing.get(index) - lastWheelOffset - trailSpacing / 2, steer); + if (probe.blocked) + return false; + recorder.accept(probe); + } + + // inside 1st bogey + probe.travel(graph, trailSpacing, steer); + if (probe.blocked) + return false; + recorder.accept(probe); + + lastWheelOffset = trailSpacing / 2; + + if (!carriage.isOnTwoBogeys()) + continue; + + double leadSpacing = carriage.leadingBogey().type.getWheelPointSpacing(); + + // between bogeys + probe.travel(graph, carriage.bogeySpacing - lastWheelOffset - leadSpacing / 2, steer); + if (probe.blocked) + return false; + recorder.accept(probe); + + // inside 2nd bogey + probe.travel(graph, leadSpacing, steer); + if (probe.blocked) + return false; + recorder.accept(probe); + + lastWheelOffset = leadSpacing / 2; + } + + if (simulate) + return true; + + train.derailed = false; + train.graph = graph; + train.migratingPoints.clear(); + train.forEachTravellingPoint(tp -> { + Pair, Double> last = recordedLocations.remove(recordedLocations.size() - 1); + tp.node1 = last.getFirst() + .getFirst(); + tp.node2 = last.getFirst() + .getSecond(); + tp.position = last.getSecond(); + tp.edge = graph.getConnectionsFrom(tp.node1) + .get(tp.node2); + }); + + train.status.successfulMigration(); + train.leave(); + return true; + } + + public static void clientTick() { + Minecraft mc = Minecraft.getInstance(); + LocalPlayer player = mc.player; + + if (player == null) + return; + if (player.isPassenger()) + return; + if (mc.level == null) + return; + + if (relocatingTrain != null) { + Train relocating = getRelocating(); + if (relocating == null) { + relocatingTrain = null; + return; + } + + if (Math.abs(relocating.speed) > 1 / 1024d) { + player.displayClientMessage(Lang.translate("train.cannot_relocate_moving") + .withStyle(ChatFormatting.RED), true); + relocatingTrain = null; + return; + } + + if (!AllItems.WRENCH.isIn(player.getMainHandItem())) { + player.displayClientMessage(Lang.translate("train.relocate.abort") + .withStyle(ChatFormatting.RED), true); + relocatingTrain = null; + return; + } + + if (!player.position() + .closerThan(relocatingOrigin, 24)) { + player.displayClientMessage(Lang.translate("train.relocate.too_far") + .withStyle(ChatFormatting.RED), true); + return; + } + + Boolean success = relocateClient(relocating, true); + if (success == null) + player.displayClientMessage(Lang.translate("train.relocate", relocating.name), true); + else if (success.booleanValue()) + player.displayClientMessage(Lang.translate("train.relocate.valid") + .withStyle(ChatFormatting.GREEN), true); + else + player.displayClientMessage(Lang.translate("train.relocate.invalid") + .withStyle(ChatFormatting.RED), true); + return; + } + + Couple rayInputs = ContraptionHandlerClient.getRayInputs(player); + Vec3 origin = rayInputs.getFirst(); + Vec3 target = rayInputs.getSecond(); + + CarriageContraptionEntity currentEntity = hoveredEntity.get(); + if (currentEntity != null) { + if (ContraptionHandlerClient.rayTraceContraption(origin, target, currentEntity) != null) + return; + hoveredEntity = new WeakReference<>(null); + } + + AABB aabb = new AABB(origin, target); + List intersectingContraptions = + mc.level.getEntitiesOfClass(CarriageContraptionEntity.class, aabb); + + for (CarriageContraptionEntity contraptionEntity : intersectingContraptions) { + if (ContraptionHandlerClient.rayTraceContraption(origin, target, contraptionEntity) == null) + continue; + hoveredEntity = new WeakReference<>(contraptionEntity); + } + } + + public static boolean carriageWrenched(Vec3 vec3, CarriageContraptionEntity entity) { + Train train = getTrainFromEntity(entity); + if (train != null && !train.heldForAssembly) { + relocatingOrigin = vec3; + relocatingTrain = train.id; + return true; + } + return false; + } + + public static boolean addToTooltip(List tooltip, boolean shiftKeyDown) { + Train train = getTrainFromEntity(hoveredEntity.get()); + if (train != null && train.derailed) { + TooltipHelper.addHint(tooltip, "hint.derailed_train"); + return true; + } + return false; + } + + private static Train getRelocating() { + if (relocatingTrain == null) + return null; + return Create.RAILWAYS.trains.get(relocatingTrain); // TODO: thread breach + } + + private static Train getTrainFromEntity(CarriageContraptionEntity carriageContraptionEntity) { + if (carriageContraptionEntity == null) + return null; + int id = ((CarriageContraption) carriageContraptionEntity.getContraption()).temporaryCarriageIdHolder; + Carriage carriage = Create.RAILWAYS.carriageById.get(id); // TODO: thread breach + if (carriage == null) + return null; + return carriage.train; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainStatus.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainStatus.java index 7dd8d85fc..cf3be4f2c 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainStatus.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainStatus.java @@ -50,6 +50,10 @@ public class TrainStatus { displayInformation("A Carriage has reached the end of its Track.", false); track = true; } + + public void crash() { + displayInformation("Collision with other Train", false); + } public void successfulMigration() { if (!track) diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TravellingPoint.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/TravellingPoint.java index 0411e88ba..7ad7aa39b 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TravellingPoint.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/TravellingPoint.java @@ -172,7 +172,7 @@ public class TravellingPoint { position -= edgeLength; edgeLength = edge.getLength(node1, node2); } - + return traveled; } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/ScheduleRuntime.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/ScheduleRuntime.java index d9a5b3f5e..8da5ac817 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/ScheduleRuntime.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/management/ScheduleRuntime.java @@ -63,6 +63,8 @@ public class ScheduleRuntime { return; if (paused) return; + if (train.derailed) + return; if (train.navigation.destination != null) return; if (currentEntry >= schedule.entries.size()) { @@ -129,7 +131,8 @@ public class ScheduleRuntime { for (GlobalStation globalStation : train.graph.getStations()) { if (!globalStation.name.matches(regex)) continue; - double cost = train.navigation.startNavigation(globalStation, true); + boolean matchesCurrent = train.currentStation != null && train.currentStation.equals(globalStation.id); + double cost = matchesCurrent ? 0 : train.navigation.startNavigation(globalStation, true); if (cost < 0) continue; if (cost > bestCost) diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/StationBlock.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/StationBlock.java index b63091e02..6c1c6a5a9 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/StationBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/management/StationBlock.java @@ -3,6 +3,7 @@ package com.simibubi.create.content.logistics.trains.management; import com.simibubi.create.AllItems; import com.simibubi.create.AllShapes; import com.simibubi.create.AllTileEntities; +import com.simibubi.create.Create; import com.simibubi.create.foundation.block.ITE; import com.simibubi.create.foundation.gui.ScreenOpener; @@ -14,6 +15,7 @@ import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.CreativeModeTab; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; @@ -59,6 +61,10 @@ public class StationBlock extends HorizontalDirectionalBlock implements ITE () -> withTileEntityDo(pLevel, pPos, te -> this.displayScreen(te, pPlayer))); return InteractionResult.SUCCESS; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/StationTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/StationTileEntity.java index 1e4befa9e..74c9b0588 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/StationTileEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/management/StationTileEntity.java @@ -204,9 +204,6 @@ public class StationTileEntity extends SmartTileEntity { axisFound = true; } - Create.RAILWAYS.trains.clear(); - Create.RAILWAYS.carriageById.clear(); - return true; } @@ -475,10 +472,6 @@ public class StationTileEntity extends SmartTileEntity { contraption.expandBoundsAroundAxis(Axis.Y); } - Create.RAILWAYS.carriageById.values() - .forEach(Carriage::discardEntity); - Create.RAILWAYS.carriageById.clear(); - Train train = new Train(UUID.randomUUID(), playerUUID, graph, carriages, spacing); GlobalStation station = getOrCreateGlobalStation(); train.setCurrentStation(station); diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/TrackTargetingBehaviour.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/TrackTargetingBehaviour.java index 4f66ae428..9d4911ab3 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/TrackTargetingBehaviour.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/management/TrackTargetingBehaviour.java @@ -1,21 +1,13 @@ package com.simibubi.create.content.logistics.trains.management; -import java.util.List; - import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.Create; import com.simibubi.create.content.logistics.trains.ITrackBlock; -import com.simibubi.create.content.logistics.trains.TrackGraph; -import com.simibubi.create.content.logistics.trains.TrackNode; -import com.simibubi.create.content.logistics.trains.TrackNodeLocation.DiscoveredLocation; -import com.simibubi.create.content.logistics.trains.TrackPropagator; +import com.simibubi.create.content.logistics.trains.TrackGraphHelper; import com.simibubi.create.foundation.render.CachedBufferer; import com.simibubi.create.foundation.render.SuperByteBuffer; import com.simibubi.create.foundation.tileEntity.SmartTileEntity; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.BehaviourType; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Pair; import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.client.renderer.MultiBufferSource; @@ -24,11 +16,9 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Direction.AxisDirection; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtUtils; -import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -85,71 +75,7 @@ public class TrackTargetingBehaviour extends TileEntityBehaviour { } public GraphLocation determineGraphLocation() { - Level level = getWorld(); - BlockPos pos = getGlobalPosition(); - BlockState trackBlockState = getTrackBlockState(); - ITrackBlock track = getTrack(); - if (track == null) - return null; - - Vec3 axis = track.getTrackAxis(level, pos, trackBlockState) - .scale(getTargetDirection().getStep()); - double length = axis.length(); - - List> ends = - TrackPropagator.getEnds(level, pos, trackBlockState, null, true); - - TrackGraph graph = null; - TrackNode frontNode = null; - TrackNode backNode = null; - double position = 0; - - for (Pair pair : ends) { - DiscoveredLocation current = pair.getSecond(); - BlockPos currentPos = pair.getFirst(); - Vec3 offset = Vec3.atLowerCornerOf(currentPos.subtract(pos)); - boolean forward = offset.distanceToSqr(axis.scale(-1)) < 1 / 4096f; - boolean backwards = offset.distanceToSqr(axis) < 1 / 4096f; - - if (!forward && !backwards) - continue; - - for (int i = 0; i < 32; i++) { - DiscoveredLocation loc = current; - List> list = - TrackPropagator.getEnds(level, currentPos, level.getBlockState(currentPos), current, true); - if (!list.isEmpty()) { - currentPos = list.get(0) - .getFirst(); - current = list.get(0) - .getSecond(); - } - - if (graph == null) - graph = Create.RAILWAYS.getGraph(level, loc); - if (graph == null) - continue; - TrackNode node = graph.locateNode(loc); - if (node == null) - continue; - if (forward) - frontNode = node; - if (backwards) { - backNode = node; - position = (i + .5) * length; - } - break; - } - } - - if (frontNode == null || backNode == null) - return null; - - GraphLocation graphLocation = new GraphLocation(); - graphLocation.edge = Couple.create(backNode.getLocation(), frontNode.getLocation()); - graphLocation.position = position; - graphLocation.graph = graph; - return graphLocation; + return TrackGraphHelper.getGraphLocationAt(getWorld(), getGlobalPosition(), getTargetDirection()); } @OnlyIn(Dist.CLIENT) diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/TrackTargetingBlockItem.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/TrackTargetingBlockItem.java index fa5851172..c87ea19e1 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/TrackTargetingBlockItem.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/management/TrackTargetingBlockItem.java @@ -2,6 +2,7 @@ package com.simibubi.create.content.logistics.trains.management; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.content.logistics.trains.ITrackBlock; +import com.simibubi.create.content.logistics.trains.TrackGraphHelper; import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; import com.simibubi.create.foundation.utility.Lang; @@ -17,6 +18,7 @@ import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; public class TrackTargetingBlockItem extends BlockItem { @@ -43,12 +45,12 @@ public class TrackTargetingBlockItem extends BlockItem { return InteractionResult.SUCCESS; } - if (state.getBlock() instanceof ITrackBlock track) { + if (state.getBlock()instanceof ITrackBlock track) { if (level.isClientSide) return InteractionResult.SUCCESS; CompoundTag stackTag = stack.getOrCreateTag(); - boolean front = player.getLookAngle() - .dot(track.getTrackAxis(level, pos, state)) < 0; + Vec3 lookAngle = player.getLookAngle(); + boolean front = TrackGraphHelper.getTrackDirectionByLookVec(lookAngle, level, pos, state, track); stackTag.put("SelectedPos", NbtUtils.writeBlockPos(pos)); stackTag.putBoolean("SelectedDirection", front); player.displayClientMessage(Lang.translate("track_target.set"), true); @@ -69,7 +71,7 @@ public class TrackTargetingBlockItem extends BlockItem { BlockPos selectedPos = NbtUtils.readBlockPos(tag.getCompound("SelectedPos")); BlockPos placedPos = pos.relative(pContext.getClickedFace(), state.getMaterial() .isReplaceable() ? 0 : 1); - + if (!selectedPos.closerThan(placedPos, 16)) { player.displayClientMessage(Lang.translate("track_target.too_far") .withStyle(ChatFormatting.RED), true); diff --git a/src/main/java/com/simibubi/create/events/ClientEvents.java b/src/main/java/com/simibubi/create/events/ClientEvents.java index 57c7faeec..940992791 100644 --- a/src/main/java/com/simibubi/create/events/ClientEvents.java +++ b/src/main/java/com/simibubi/create/events/ClientEvents.java @@ -33,6 +33,7 @@ import com.simibubi.create.content.logistics.block.depot.EjectorTargetHandler; import com.simibubi.create.content.logistics.block.mechanicalArm.ArmInteractionPointHandler; import com.simibubi.create.content.logistics.item.LinkedControllerClientHandler; import com.simibubi.create.content.logistics.trains.entity.CarriageCouplingRenderer; +import com.simibubi.create.content.logistics.trains.entity.TrainRelocator; import com.simibubi.create.content.logistics.trains.management.TrackTargetingBlockItem; import com.simibubi.create.content.logistics.trains.track.TrackPlacement; import com.simibubi.create.foundation.config.AllConfigs; @@ -150,6 +151,7 @@ public class ClientEvents { ToolboxHandlerClient.clientTick(); TrackTargetingBlockItem.clientTick(); TrackPlacement.clientTick(); + TrainRelocator.clientTick(); } @SubscribeEvent diff --git a/src/main/java/com/simibubi/create/events/InputEvents.java b/src/main/java/com/simibubi/create/events/InputEvents.java index a10f20add..98b70788b 100644 --- a/src/main/java/com/simibubi/create/events/InputEvents.java +++ b/src/main/java/com/simibubi/create/events/InputEvents.java @@ -3,6 +3,7 @@ package com.simibubi.create.events; import com.simibubi.create.CreateClient; import com.simibubi.create.content.curiosities.toolbox.ToolboxHandlerClient; import com.simibubi.create.content.logistics.item.LinkedControllerClientHandler; +import com.simibubi.create.content.logistics.trains.entity.TrainRelocator; import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringHandler; import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueHandler; @@ -38,8 +39,8 @@ public class InputEvents { double delta = event.getScrollDelta(); // CollisionDebugger.onScroll(delta); boolean cancelled = CreateClient.SCHEMATIC_HANDLER.mouseScrolled(delta) - || CreateClient.SCHEMATIC_AND_QUILL_HANDLER.mouseScrolled(delta) || FilteringHandler.onScroll(delta) - || ScrollValueHandler.onScroll(delta); + || CreateClient.SCHEMATIC_AND_QUILL_HANDLER.mouseScrolled(delta) || FilteringHandler.onScroll(delta) + || ScrollValueHandler.onScroll(delta); event.setCanceled(cancelled); } @@ -59,15 +60,18 @@ public class InputEvents { public static void onClickInput(ClickInputEvent event) { if (Minecraft.getInstance().screen != null) return; - + if (event.getKeyMapping() == Minecraft.getInstance().options.keyPickItem) { if (ToolboxHandlerClient.onPickItem()) event.setCanceled(true); return; } - - if (event.isUseItem()) - LinkedControllerClientHandler.deactivateInLectern(); + + if (!event.isUseItem()) + return; + + LinkedControllerClientHandler.deactivateInLectern(); + TrainRelocator.onClicked(event); } } diff --git a/src/main/resources/assets/create/lang/default/interface.json b/src/main/resources/assets/create/lang/default/interface.json index 7656b6bd6..048e5294f 100644 --- a/src/main/resources/assets/create/lang/default/interface.json +++ b/src/main/resources/assets/create/lang/default/interface.json @@ -550,6 +550,9 @@ "create.hint.full_deployer.title": "Deployer Item Overflow", "create.hint.full_deployer": "It appears this _Deployer_ contains _excess_ _items_ that need to be _extracted._ Use a _hopper,_ _funnel_ or other means to free it from its overflow.", + "create.hint.derailed_train.title": "Derailed Train", + "create.hint.derailed_train": "It appears this _Train_ is no longer sitting on a connected track piece. _Right-Click_ using a _wrench_ in order to relocate it to a nearby track.", + "create.gui.schedule.lmb_edit": "Left-Click to Edit", "create.gui.schedule.rmb_remove": "Right-Click to Remove", "create.gui.schedule.duplicate": "Duplicate", @@ -632,6 +635,13 @@ "create.track_target.too_far": "Targeted track is too far from here", "create.train.unnamed": "Unnamed Train", + "create.train.cannot_relocate_moving": "Cannot relocate a moving Train", + "create.train.relocate": "Click a Track to Relocate %1$s to. Sneak-Click to abort", + "create.train.relocate.abort": "Relocation aborted", + "create.train.relocate.success": "Relocation successful", + "create.train.relocate.valid": "Can relocate to here, Click to Confirm", + "create.train.relocate.invalid": "Cannot relocate Train to this Track", + "create.train.relocate.too_far": "Cannot relocate Train this far away", "create.gui.config.overlay1": "Hi :)", "create.gui.config.overlay2": "This is a sample overlay",