From 0a931a77ef19e1920a9f3e8fbefdba324099e5cf Mon Sep 17 00:00:00 2001 From: simibubi <31564874+simibubi@users.noreply.github.com> Date: Sat, 5 Feb 2022 02:06:31 +0100 Subject: [PATCH] Manual Steering - Trains can now travel backwards through the graph - Controls are now a requirement for assembly - Double-endedness now depends on two opposite controls blocks anywhere on the train - Players can now manually control trains via a mounted controls block --- src/generated/resources/.cache/cache | 32 +-- .../resources/assets/create/lang/en_us.json | 8 +- .../assets/create/lang/unfinished/de_de.json | 10 +- .../assets/create/lang/unfinished/es_cl.json | 10 +- .../assets/create/lang/unfinished/es_es.json | 10 +- .../assets/create/lang/unfinished/fr_fr.json | 10 +- .../assets/create/lang/unfinished/it_it.json | 10 +- .../assets/create/lang/unfinished/ja_jp.json | 10 +- .../assets/create/lang/unfinished/ko_kr.json | 10 +- .../assets/create/lang/unfinished/nl_nl.json | 10 +- .../assets/create/lang/unfinished/pl_pl.json | 10 +- .../assets/create/lang/unfinished/pt_br.json | 10 +- .../assets/create/lang/unfinished/pt_pt.json | 10 +- .../assets/create/lang/unfinished/ru_ru.json | 10 +- .../assets/create/lang/unfinished/zh_cn.json | 10 +- .../assets/create/lang/unfinished/zh_tw.json | 10 +- .../data/create/advancements/aesthetics.json | 4 +- .../create/AllInteractionBehaviours.java | 2 + .../java/com/simibubi/create/AllShapes.java | 2 +- .../AbstractContraptionEntity.java | 26 +- .../ContraptionHandlerClient.java | 6 +- .../interaction/controls/ControlsHandler.java | 135 +++++++++++ .../ControlsInteractionBehaviour.java | 20 ++ .../controls/ControlsMovementBehaviour.java | 38 ++- .../controls/ControlsRenderer.java | 30 ++- .../item/LinkedControllerClientHandler.java | 34 +-- .../item/LinkedControllerScreen.java | 3 +- .../logistics/trains/entity/Carriage.java | 31 ++- .../trains/entity/CarriageContraption.java | 33 ++- .../entity/CarriageContraptionEntity.java | 172 ++++++++++++- .../CarriageContraptionEntityRenderer.java | 4 +- .../logistics/trains/entity/Navigation.java | 149 ++++++++---- .../logistics/trains/entity/Train.java | 51 +++- .../trains/entity/TrainRelocator.java | 5 +- .../logistics/trains/entity/TrainStatus.java | 4 + .../trains/entity/TravellingPoint.java | 121 +++++++--- .../trains/management/StationTileEntity.java | 7 + .../simibubi/create/events/ClientEvents.java | 2 + .../foundation/utility/ControlsUtil.java | 37 +++ .../assets/create/lang/default/interface.json | 6 + .../models/block/controls/block_closed.json | 51 ++-- .../models/block/controls/block_open.json | 90 ++++--- .../create/models/block/controls/item.json | 226 +++++++++++------- .../models/block/controls/train/cover.json | 18 +- 44 files changed, 1123 insertions(+), 364 deletions(-) create mode 100644 src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsHandler.java create mode 100644 src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsInteractionBehaviour.java create mode 100644 src/main/java/com/simibubi/create/foundation/utility/ControlsUtil.java diff --git a/src/generated/resources/.cache/cache b/src/generated/resources/.cache/cache index 5248f581b..281622e95 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 -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 +9dc50a1957cac1967adba6a02f2708f5a82915b6 assets/create/lang/en_us.json +60e216704dc824ae189af3927ae06e4c70e53478 assets/create/lang/unfinished/de_de.json +c2faed3f8cdc2616dc03d6c9cf6dafd9084c3e14 assets/create/lang/unfinished/es_cl.json +f9632799fdf6278d0b0c0a2bff40df099745b076 assets/create/lang/unfinished/es_es.json +1d7af6b083679766bb542cf61fc6a835983a055c assets/create/lang/unfinished/fr_fr.json +4942f180ef3758a1449108331943e0fa75e1a29b assets/create/lang/unfinished/it_it.json +3249596dacdf06bc727676a5cc8acf85742054d0 assets/create/lang/unfinished/ja_jp.json +ef7601ee26fdaf0356fe5400bc4f230ccb87eea8 assets/create/lang/unfinished/ko_kr.json +6d3914298d06db106d91299729f39cf5406f6768 assets/create/lang/unfinished/nl_nl.json +e21bd53612d2e82e9214b94fd6d2d110377089c1 assets/create/lang/unfinished/pl_pl.json +56b4b8f892bf4442ac2f5140dc97273d1dfe2f27 assets/create/lang/unfinished/pt_br.json +63690bcfce50698d81562fe6cff1d0701a13e23d assets/create/lang/unfinished/pt_pt.json +dfa8dc43216673feac87a2a49d08fd8cc9b1d9f2 assets/create/lang/unfinished/ru_ru.json +dd18a29b4a76752ea033569ebbb07014e9aa3ab0 assets/create/lang/unfinished/zh_cn.json +0b67d5808e2665b5c0414a103b730508e17e01f6 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 -5d0cc4c0255dc241e61c173b31ddca70c88d08e4 data/create/advancements/aesthetics.json +0f1b4b980afba9bf2caf583b88e261bba8b10313 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 8b48e101f..0f055c52b 100644 --- a/src/generated/resources/assets/create/lang/en_us.json +++ b/src/generated/resources/assets/create/lang/en_us.json @@ -1398,6 +1398,8 @@ "create.train_assembly.not_connected_in_order": "Bogeys are not connected in order", "create.train_assembly.single_bogey_carriage": "This Bogey type cannot support a carriage on its own", "create.train_assembly.nothing_attached": "No structure attached to Bogey %1$s", + "create.train_assembly.no_controls": "At least one forward-facing controls block needs to be mounted on the train", + "create.train_assembly.sideways_controls": "A mounted controls block is facing sideways", "create.track_target.set": "Targeted track selected", "create.track_target.success": "Successfully bound to targeted track", @@ -1410,10 +1412,14 @@ "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.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.contraption.controls.start_controlling": "Now controlling: %1$s", + "create.contraption.controls.stop_controlling": "Stopped controlling contraption", + "create.contraption.controls.approach_station": "Hold %1$s to approach %2$s", + "create.gui.config.overlay1": "Hi :)", "create.gui.config.overlay2": "This is a sample overlay", "create.gui.config.overlay3": "Click or drag with your mouse", 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 0f7b6bc74..ddf1acf08 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: 1422", + "_": "Missing Localizations: 1427", "_": "->------------------------] Game Elements [------------------------<-", @@ -1399,6 +1399,8 @@ "create.train_assembly.not_connected_in_order": "UNLOCALIZED: Bogeys are not connected in order", "create.train_assembly.single_bogey_carriage": "UNLOCALIZED: This Bogey type cannot support a carriage on its own", "create.train_assembly.nothing_attached": "UNLOCALIZED: No structure attached to Bogey %1$s", + "create.train_assembly.no_controls": "UNLOCALIZED: At least one forward-facing controls block needs to be mounted on the train", + "create.train_assembly.sideways_controls": "UNLOCALIZED: A mounted controls block is facing sideways", "create.track_target.set": "UNLOCALIZED: Targeted track selected", "create.track_target.success": "UNLOCALIZED: Successfully bound to targeted track", @@ -1411,10 +1413,14 @@ "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.valid": "UNLOCALIZED: Can relocate to 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.contraption.controls.start_controlling": "UNLOCALIZED: Now controlling: %1$s", + "create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption", + "create.contraption.controls.approach_station": "UNLOCALIZED: Hold %1$s to approach %2$s", + "create.gui.config.overlay1": "Hi :)", "create.gui.config.overlay2": "Dies ist ein Beispiel Overlay", "create.gui.config.overlay3": "Klicke oder ziehe mit deiner Maus", 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 2e244fafb..e21e286b1 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: 433", + "_": "Missing Localizations: 438", "_": "->------------------------] Game Elements [------------------------<-", @@ -1399,6 +1399,8 @@ "create.train_assembly.not_connected_in_order": "UNLOCALIZED: Bogeys are not connected in order", "create.train_assembly.single_bogey_carriage": "UNLOCALIZED: This Bogey type cannot support a carriage on its own", "create.train_assembly.nothing_attached": "UNLOCALIZED: No structure attached to Bogey %1$s", + "create.train_assembly.no_controls": "UNLOCALIZED: At least one forward-facing controls block needs to be mounted on the train", + "create.train_assembly.sideways_controls": "UNLOCALIZED: A mounted controls block is facing sideways", "create.track_target.set": "UNLOCALIZED: Targeted track selected", "create.track_target.success": "UNLOCALIZED: Successfully bound to targeted track", @@ -1411,10 +1413,14 @@ "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.valid": "UNLOCALIZED: Can relocate to 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.contraption.controls.start_controlling": "UNLOCALIZED: Now controlling: %1$s", + "create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption", + "create.contraption.controls.approach_station": "UNLOCALIZED: Hold %1$s to approach %2$s", + "create.gui.config.overlay1": "Hola :)", "create.gui.config.overlay2": "Este es un overlay de ejemplo", "create.gui.config.overlay3": "Haz clic o arrastra con el mouse", 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 482f7663d..237497570 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: 433", + "_": "Missing Localizations: 438", "_": "->------------------------] Game Elements [------------------------<-", @@ -1399,6 +1399,8 @@ "create.train_assembly.not_connected_in_order": "UNLOCALIZED: Bogeys are not connected in order", "create.train_assembly.single_bogey_carriage": "UNLOCALIZED: This Bogey type cannot support a carriage on its own", "create.train_assembly.nothing_attached": "UNLOCALIZED: No structure attached to Bogey %1$s", + "create.train_assembly.no_controls": "UNLOCALIZED: At least one forward-facing controls block needs to be mounted on the train", + "create.train_assembly.sideways_controls": "UNLOCALIZED: A mounted controls block is facing sideways", "create.track_target.set": "UNLOCALIZED: Targeted track selected", "create.track_target.success": "UNLOCALIZED: Successfully bound to targeted track", @@ -1411,10 +1413,14 @@ "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.valid": "UNLOCALIZED: Can relocate to 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.contraption.controls.start_controlling": "UNLOCALIZED: Now controlling: %1$s", + "create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption", + "create.contraption.controls.approach_station": "UNLOCALIZED: Hold %1$s to approach %2$s", + "create.gui.config.overlay1": "Hola :)", "create.gui.config.overlay2": "Esta es una muestra de la superposición", "create.gui.config.overlay3": "Haga clic o arrastre con el rató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 72276edf9..1ac54776d 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: 1684", + "_": "Missing Localizations: 1689", "_": "->------------------------] Game Elements [------------------------<-", @@ -1399,6 +1399,8 @@ "create.train_assembly.not_connected_in_order": "UNLOCALIZED: Bogeys are not connected in order", "create.train_assembly.single_bogey_carriage": "UNLOCALIZED: This Bogey type cannot support a carriage on its own", "create.train_assembly.nothing_attached": "UNLOCALIZED: No structure attached to Bogey %1$s", + "create.train_assembly.no_controls": "UNLOCALIZED: At least one forward-facing controls block needs to be mounted on the train", + "create.train_assembly.sideways_controls": "UNLOCALIZED: A mounted controls block is facing sideways", "create.track_target.set": "UNLOCALIZED: Targeted track selected", "create.track_target.success": "UNLOCALIZED: Successfully bound to targeted track", @@ -1411,10 +1413,14 @@ "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.valid": "UNLOCALIZED: Can relocate to 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.contraption.controls.start_controlling": "UNLOCALIZED: Now controlling: %1$s", + "create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption", + "create.contraption.controls.approach_station": "UNLOCALIZED: Hold %1$s to approach %2$s", + "create.gui.config.overlay1": "UNLOCALIZED: Hi :)", "create.gui.config.overlay2": "UNLOCALIZED: This is a sample overlay", "create.gui.config.overlay3": "UNLOCALIZED: Click or drag with your mouse", 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 f6047c3ed..620986964 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: 1373", + "_": "Missing Localizations: 1378", "_": "->------------------------] Game Elements [------------------------<-", @@ -1399,6 +1399,8 @@ "create.train_assembly.not_connected_in_order": "UNLOCALIZED: Bogeys are not connected in order", "create.train_assembly.single_bogey_carriage": "UNLOCALIZED: This Bogey type cannot support a carriage on its own", "create.train_assembly.nothing_attached": "UNLOCALIZED: No structure attached to Bogey %1$s", + "create.train_assembly.no_controls": "UNLOCALIZED: At least one forward-facing controls block needs to be mounted on the train", + "create.train_assembly.sideways_controls": "UNLOCALIZED: A mounted controls block is facing sideways", "create.track_target.set": "UNLOCALIZED: Targeted track selected", "create.track_target.success": "UNLOCALIZED: Successfully bound to targeted track", @@ -1411,10 +1413,14 @@ "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.valid": "UNLOCALIZED: Can relocate to 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.contraption.controls.start_controlling": "UNLOCALIZED: Now controlling: %1$s", + "create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption", + "create.contraption.controls.approach_station": "UNLOCALIZED: Hold %1$s to approach %2$s", + "create.gui.config.overlay1": "Ciao :)", "create.gui.config.overlay2": "Questo overlay è di esempio", "create.gui.config.overlay3": "Cliccalo o trascinalo col mouse", 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 65c116869..c04445efd 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: 103", + "_": "Missing Localizations: 108", "_": "->------------------------] Game Elements [------------------------<-", @@ -1399,6 +1399,8 @@ "create.train_assembly.not_connected_in_order": "UNLOCALIZED: Bogeys are not connected in order", "create.train_assembly.single_bogey_carriage": "UNLOCALIZED: This Bogey type cannot support a carriage on its own", "create.train_assembly.nothing_attached": "UNLOCALIZED: No structure attached to Bogey %1$s", + "create.train_assembly.no_controls": "UNLOCALIZED: At least one forward-facing controls block needs to be mounted on the train", + "create.train_assembly.sideways_controls": "UNLOCALIZED: A mounted controls block is facing sideways", "create.track_target.set": "UNLOCALIZED: Targeted track selected", "create.track_target.success": "UNLOCALIZED: Successfully bound to targeted track", @@ -1411,10 +1413,14 @@ "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.valid": "UNLOCALIZED: Can relocate to 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.contraption.controls.start_controlling": "UNLOCALIZED: Now controlling: %1$s", + "create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption", + "create.contraption.controls.approach_station": "UNLOCALIZED: Hold %1$s to approach %2$s", + "create.gui.config.overlay1": "やぁ(・∀・)", "create.gui.config.overlay2": "これはオーバーレイのサンプルです", "create.gui.config.overlay3": "マウスでクリックまたはドラッグしてください", 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 675fc2150..03476ab9a 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: 105", + "_": "Missing Localizations: 110", "_": "->------------------------] Game Elements [------------------------<-", @@ -1399,6 +1399,8 @@ "create.train_assembly.not_connected_in_order": "UNLOCALIZED: Bogeys are not connected in order", "create.train_assembly.single_bogey_carriage": "UNLOCALIZED: This Bogey type cannot support a carriage on its own", "create.train_assembly.nothing_attached": "UNLOCALIZED: No structure attached to Bogey %1$s", + "create.train_assembly.no_controls": "UNLOCALIZED: At least one forward-facing controls block needs to be mounted on the train", + "create.train_assembly.sideways_controls": "UNLOCALIZED: A mounted controls block is facing sideways", "create.track_target.set": "UNLOCALIZED: Targeted track selected", "create.track_target.success": "UNLOCALIZED: Successfully bound to targeted track", @@ -1411,10 +1413,14 @@ "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.valid": "UNLOCALIZED: Can relocate to 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.contraption.controls.start_controlling": "UNLOCALIZED: Now controlling: %1$s", + "create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption", + "create.contraption.controls.approach_station": "UNLOCALIZED: Hold %1$s to approach %2$s", + "create.gui.config.overlay1": "Hi :)", "create.gui.config.overlay2": "This is a sample overlay", "create.gui.config.overlay3": "Click or drag with your mouse", 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 5d717288c..19710f125 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: 2037", + "_": "Missing Localizations: 2042", "_": "->------------------------] Game Elements [------------------------<-", @@ -1399,6 +1399,8 @@ "create.train_assembly.not_connected_in_order": "UNLOCALIZED: Bogeys are not connected in order", "create.train_assembly.single_bogey_carriage": "UNLOCALIZED: This Bogey type cannot support a carriage on its own", "create.train_assembly.nothing_attached": "UNLOCALIZED: No structure attached to Bogey %1$s", + "create.train_assembly.no_controls": "UNLOCALIZED: At least one forward-facing controls block needs to be mounted on the train", + "create.train_assembly.sideways_controls": "UNLOCALIZED: A mounted controls block is facing sideways", "create.track_target.set": "UNLOCALIZED: Targeted track selected", "create.track_target.success": "UNLOCALIZED: Successfully bound to targeted track", @@ -1411,10 +1413,14 @@ "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.valid": "UNLOCALIZED: Can relocate to 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.contraption.controls.start_controlling": "UNLOCALIZED: Now controlling: %1$s", + "create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption", + "create.contraption.controls.approach_station": "UNLOCALIZED: Hold %1$s to approach %2$s", + "create.gui.config.overlay1": "UNLOCALIZED: Hi :)", "create.gui.config.overlay2": "UNLOCALIZED: This is a sample overlay", "create.gui.config.overlay3": "UNLOCALIZED: Click or drag with your mouse", 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 8cbb2a299..9d6a7e68e 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: 472", + "_": "Missing Localizations: 477", "_": "->------------------------] Game Elements [------------------------<-", @@ -1399,6 +1399,8 @@ "create.train_assembly.not_connected_in_order": "UNLOCALIZED: Bogeys are not connected in order", "create.train_assembly.single_bogey_carriage": "UNLOCALIZED: This Bogey type cannot support a carriage on its own", "create.train_assembly.nothing_attached": "UNLOCALIZED: No structure attached to Bogey %1$s", + "create.train_assembly.no_controls": "UNLOCALIZED: At least one forward-facing controls block needs to be mounted on the train", + "create.train_assembly.sideways_controls": "UNLOCALIZED: A mounted controls block is facing sideways", "create.track_target.set": "UNLOCALIZED: Targeted track selected", "create.track_target.success": "UNLOCALIZED: Successfully bound to targeted track", @@ -1411,10 +1413,14 @@ "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.valid": "UNLOCALIZED: Can relocate to 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.contraption.controls.start_controlling": "UNLOCALIZED: Now controlling: %1$s", + "create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption", + "create.contraption.controls.approach_station": "UNLOCALIZED: Hold %1$s to approach %2$s", + "create.gui.config.overlay1": "Cześć :)", "create.gui.config.overlay2": "To jest przykładowa nakładka", "create.gui.config.overlay3": "Kliknij lub przeciągnij myszką", 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 3dbc40c85..6871fab36 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: 1656", + "_": "Missing Localizations: 1661", "_": "->------------------------] Game Elements [------------------------<-", @@ -1399,6 +1399,8 @@ "create.train_assembly.not_connected_in_order": "UNLOCALIZED: Bogeys are not connected in order", "create.train_assembly.single_bogey_carriage": "UNLOCALIZED: This Bogey type cannot support a carriage on its own", "create.train_assembly.nothing_attached": "UNLOCALIZED: No structure attached to Bogey %1$s", + "create.train_assembly.no_controls": "UNLOCALIZED: At least one forward-facing controls block needs to be mounted on the train", + "create.train_assembly.sideways_controls": "UNLOCALIZED: A mounted controls block is facing sideways", "create.track_target.set": "UNLOCALIZED: Targeted track selected", "create.track_target.success": "UNLOCALIZED: Successfully bound to targeted track", @@ -1411,10 +1413,14 @@ "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.valid": "UNLOCALIZED: Can relocate to 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.contraption.controls.start_controlling": "UNLOCALIZED: Now controlling: %1$s", + "create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption", + "create.contraption.controls.approach_station": "UNLOCALIZED: Hold %1$s to approach %2$s", + "create.gui.config.overlay1": "UNLOCALIZED: Hi :)", "create.gui.config.overlay2": "UNLOCALIZED: This is a sample overlay", "create.gui.config.overlay3": "UNLOCALIZED: Click or drag with your mouse", 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 5f1f58004..1f78c6add 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: 1656", + "_": "Missing Localizations: 1661", "_": "->------------------------] Game Elements [------------------------<-", @@ -1399,6 +1399,8 @@ "create.train_assembly.not_connected_in_order": "UNLOCALIZED: Bogeys are not connected in order", "create.train_assembly.single_bogey_carriage": "UNLOCALIZED: This Bogey type cannot support a carriage on its own", "create.train_assembly.nothing_attached": "UNLOCALIZED: No structure attached to Bogey %1$s", + "create.train_assembly.no_controls": "UNLOCALIZED: At least one forward-facing controls block needs to be mounted on the train", + "create.train_assembly.sideways_controls": "UNLOCALIZED: A mounted controls block is facing sideways", "create.track_target.set": "UNLOCALIZED: Targeted track selected", "create.track_target.success": "UNLOCALIZED: Successfully bound to targeted track", @@ -1411,10 +1413,14 @@ "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.valid": "UNLOCALIZED: Can relocate to 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.contraption.controls.start_controlling": "UNLOCALIZED: Now controlling: %1$s", + "create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption", + "create.contraption.controls.approach_station": "UNLOCALIZED: Hold %1$s to approach %2$s", + "create.gui.config.overlay1": "UNLOCALIZED: Hi :)", "create.gui.config.overlay2": "UNLOCALIZED: This is a sample overlay", "create.gui.config.overlay3": "UNLOCALIZED: Click or drag with your mouse", 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 cfd0b760a..27dcfa339 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: 477", + "_": "Missing Localizations: 482", "_": "->------------------------] Game Elements [------------------------<-", @@ -1399,6 +1399,8 @@ "create.train_assembly.not_connected_in_order": "UNLOCALIZED: Bogeys are not connected in order", "create.train_assembly.single_bogey_carriage": "UNLOCALIZED: This Bogey type cannot support a carriage on its own", "create.train_assembly.nothing_attached": "UNLOCALIZED: No structure attached to Bogey %1$s", + "create.train_assembly.no_controls": "UNLOCALIZED: At least one forward-facing controls block needs to be mounted on the train", + "create.train_assembly.sideways_controls": "UNLOCALIZED: A mounted controls block is facing sideways", "create.track_target.set": "UNLOCALIZED: Targeted track selected", "create.track_target.success": "UNLOCALIZED: Successfully bound to targeted track", @@ -1411,10 +1413,14 @@ "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.valid": "UNLOCALIZED: Can relocate to 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.contraption.controls.start_controlling": "UNLOCALIZED: Now controlling: %1$s", + "create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption", + "create.contraption.controls.approach_station": "UNLOCALIZED: Hold %1$s to approach %2$s", + "create.gui.config.overlay1": "Привет :)", "create.gui.config.overlay2": "Это образец оверлея", "create.gui.config.overlay3": "Кликни и тащи с помощью мыши", 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 8976c2bed..d54831747 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: 103", + "_": "Missing Localizations: 108", "_": "->------------------------] Game Elements [------------------------<-", @@ -1399,6 +1399,8 @@ "create.train_assembly.not_connected_in_order": "UNLOCALIZED: Bogeys are not connected in order", "create.train_assembly.single_bogey_carriage": "UNLOCALIZED: This Bogey type cannot support a carriage on its own", "create.train_assembly.nothing_attached": "UNLOCALIZED: No structure attached to Bogey %1$s", + "create.train_assembly.no_controls": "UNLOCALIZED: At least one forward-facing controls block needs to be mounted on the train", + "create.train_assembly.sideways_controls": "UNLOCALIZED: A mounted controls block is facing sideways", "create.track_target.set": "UNLOCALIZED: Targeted track selected", "create.track_target.success": "UNLOCALIZED: Successfully bound to targeted track", @@ -1411,10 +1413,14 @@ "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.valid": "UNLOCALIZED: Can relocate to 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.contraption.controls.start_controlling": "UNLOCALIZED: Now controlling: %1$s", + "create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption", + "create.contraption.controls.approach_station": "UNLOCALIZED: Hold %1$s to approach %2$s", + "create.gui.config.overlay1": "Hi :)", "create.gui.config.overlay2": "这是一个实例层", "create.gui.config.overlay3": "点击拖拽你的鼠标", 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 019a62550..64273f219 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: 491", + "_": "Missing Localizations: 496", "_": "->------------------------] Game Elements [------------------------<-", @@ -1399,6 +1399,8 @@ "create.train_assembly.not_connected_in_order": "UNLOCALIZED: Bogeys are not connected in order", "create.train_assembly.single_bogey_carriage": "UNLOCALIZED: This Bogey type cannot support a carriage on its own", "create.train_assembly.nothing_attached": "UNLOCALIZED: No structure attached to Bogey %1$s", + "create.train_assembly.no_controls": "UNLOCALIZED: At least one forward-facing controls block needs to be mounted on the train", + "create.train_assembly.sideways_controls": "UNLOCALIZED: A mounted controls block is facing sideways", "create.track_target.set": "UNLOCALIZED: Targeted track selected", "create.track_target.success": "UNLOCALIZED: Successfully bound to targeted track", @@ -1411,10 +1413,14 @@ "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.valid": "UNLOCALIZED: Can relocate to 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.contraption.controls.start_controlling": "UNLOCALIZED: Now controlling: %1$s", + "create.contraption.controls.stop_controlling": "UNLOCALIZED: Stopped controlling contraption", + "create.contraption.controls.approach_station": "UNLOCALIZED: Hold %1$s to approach %2$s", + "create.gui.config.overlay1": "嗨 :)", "create.gui.config.overlay2": "這是一個實例層", "create.gui.config.overlay3": "點擊拖拽你的滑鼠", diff --git a/src/generated/resources/data/create/advancements/aesthetics.json b/src/generated/resources/data/create/advancements/aesthetics.json index 59a86f429..d723cbe38 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:large_cogwheel", - "create:cogwheel" + "create:cogwheel", + "create:large_cogwheel" ] } }, diff --git a/src/main/java/com/simibubi/create/AllInteractionBehaviours.java b/src/main/java/com/simibubi/create/AllInteractionBehaviours.java index ab459251d..7d61dcb09 100644 --- a/src/main/java/com/simibubi/create/AllInteractionBehaviours.java +++ b/src/main/java/com/simibubi/create/AllInteractionBehaviours.java @@ -11,6 +11,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.Mov import com.simibubi.create.content.contraptions.components.structureMovement.interaction.DoorMovingInteraction; import com.simibubi.create.content.contraptions.components.structureMovement.interaction.LeverMovingInteraction; import com.simibubi.create.content.contraptions.components.structureMovement.interaction.TrapdoorMovingInteraction; +import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.ControlsInteractionBehaviour; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.block.Block; @@ -49,6 +50,7 @@ public class AllInteractionBehaviours { static void register() { addInteractionBehaviour(Blocks.LEVER.getRegistryName(), LeverMovingInteraction::new); addInteractionBehaviour(AllBlocks.DEPLOYER.getId(), DeployerMovingInteraction::new); + addInteractionBehaviour(AllBlocks.CONTROLS.getId(), ControlsInteractionBehaviour::new); // TODO: Scan registry for instanceof (-> modded door support) diff --git a/src/main/java/com/simibubi/create/AllShapes.java b/src/main/java/com/simibubi/create/AllShapes.java index 0db46167d..5512d7335 100644 --- a/src/main/java/com/simibubi/create/AllShapes.java +++ b/src/main/java/com/simibubi/create/AllShapes.java @@ -123,7 +123,7 @@ public class AllShapes { STATION = shape(0, 0, 0, 16, 5, 16).add(2, 4, 0, 14, 16, 4) .forHorizontal(NORTH), - CONTROLS = shape(0, 0, 4, 16, 8, 16).add(0, 0, 6, 16, 14, 16) + CONTROLS = shape(0, 0, 4, 16, 4, 16).add(0, 0, 6, 16, 14, 16) .forHorizontal(NORTH) ; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntity.java index 07a1d4811..ed3279d5a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntity.java @@ -1,6 +1,7 @@ package com.simibubi.create.content.contraptions.components.structureMovement; import java.io.IOException; +import java.util.Collection; import java.util.IdentityHashMap; import java.util.List; import java.util.Map; @@ -31,6 +32,7 @@ import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtIo; import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.Packet; import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataSerializers; @@ -161,6 +163,20 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit .size(); } + public Component getContraptionName() { + return getName(); + } + + public boolean startControlling(BlockPos controlsLocalPos) { + return false; + } + + public boolean control(BlockPos controlsLocalPos, Collection heldControls, Player player) { + return true; + } + + public void stopControlling(BlockPos controlsLocalPos) {} + public boolean handlePlayerInteraction(Player player, BlockPos localPos, Direction side, InteractionHand interactionHand) { int indexOfSeat = contraption.getSeats() @@ -168,7 +184,9 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit if (indexOfSeat == -1) return contraption.interactors.containsKey(localPos) && contraption.interactors.get(localPos) .handlePlayerInteraction(player, interactionHand, localPos, this); - + if (player.isPassenger()) + return false; + // Eject potential existing passenger Entity toDismount = null; for (Entry entry : contraption.getSeatMapping() @@ -223,7 +241,9 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit return; } - collidingEntities.entrySet().removeIf(e -> e.getValue().incrementAndGet() > 3); + collidingEntities.entrySet() + .removeIf(e -> e.getValue() + .incrementAndGet() > 3); xo = getX(); yo = getY(); @@ -441,7 +461,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit return; if (contraption == null) return; - + StructureTransform transform = makeStructureTransform(); AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> this), new ContraptionDisassemblyPacket(this.getId(), transform)); 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 7fe59d5c4..cb7b24959 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 @@ -13,8 +13,8 @@ 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 com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; @@ -74,8 +74,6 @@ public class ContraptionHandlerClient { if (player == null) return; - if (player.isPassenger()) - return; if (mc.level == null) return; if (!event.isUseItem()) @@ -84,7 +82,7 @@ public class ContraptionHandlerClient { Couple rayInputs = getRayInputs(player); Vec3 origin = rayInputs.getFirst(); Vec3 target = rayInputs.getSecond(); - AABB aabb = new AABB(origin, target); + AABB aabb = new AABB(origin, target).inflate(4); List intersectingContraptions = mc.level.getEntitiesOfClass(AbstractContraptionEntity.class, aabb); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsHandler.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsHandler.java new file mode 100644 index 000000000..3e24329be --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsHandler.java @@ -0,0 +1,135 @@ +package com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls; + +import java.lang.ref.WeakReference; +import java.util.Collection; +import java.util.HashSet; +import java.util.Vector; + +import org.lwjgl.glfw.GLFW; + +import com.mojang.blaze3d.platform.InputConstants; +import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; +import com.simibubi.create.foundation.utility.ControlsUtil; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.client.KeyMapping; +import net.minecraft.client.Minecraft; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.core.BlockPos; + +public class ControlsHandler { + + public static Collection currentlyPressed = new HashSet<>(); + + public static int PACKET_RATE = 5; + static int packetCooldown; + + static WeakReference entityRef = new WeakReference<>(null); + static BlockPos controlsPos; + + public static void controllerClicked(AbstractContraptionEntity entity, BlockPos controllerLocalPos) { + AbstractContraptionEntity prevEntity = entityRef.get(); + if (prevEntity != null) { + stopControlling(); + if (prevEntity == entity) + return; + } + if (!entity.startControlling(controllerLocalPos)) + return; + entityRef = new WeakReference(entity); + controlsPos = controllerLocalPos; + Minecraft.getInstance().player.displayClientMessage( + Lang.translate("contraption.controls.start_controlling", entity.getContraptionName()), true); + } + + public static void stopControlling() { + AbstractContraptionEntity abstractContraptionEntity = entityRef.get(); + if (abstractContraptionEntity != null) + abstractContraptionEntity.stopControlling(controlsPos); + ControlsUtil.getControls() + .forEach(kb -> kb.setDown(ControlsUtil.isActuallyPressed(kb))); + packetCooldown = 0; + entityRef = new WeakReference<>(null); + controlsPos = null; +// if (!currentlyPressed.isEmpty()) +// AllPackets.channel.sendToServer(new LinkedControllerInputPacket(currentlyPressed, false)); + currentlyPressed.clear(); + Minecraft.getInstance().player.displayClientMessage(Lang.translate("contraption.controls.stop_controlling"), + true); + } + + public static void tick() { + AbstractContraptionEntity entity = entityRef.get(); + if (entity == null) + return; + if (packetCooldown > 0) + packetCooldown--; + + Minecraft mc = Minecraft.getInstance(); + LocalPlayer player = mc.player; + + if (player.isSpectator()) { + stopControlling(); + return; + } + if (InputConstants.isKeyDown(mc.getWindow() + .getWindow(), GLFW.GLFW_KEY_ESCAPE)) { + stopControlling(); + return; + } + if (!entity.toGlobalVector(VecHelper.getCenterOf(controlsPos), 1) + .closerThan(player.position(), 10)) { + stopControlling(); + return; + } + + Vector controls = ControlsUtil.getControls(); + Collection pressedKeys = new HashSet<>(); + for (int i = 0; i < controls.size(); i++) { + if (ControlsUtil.isActuallyPressed(controls.get(i))) + pressedKeys.add(i); + } + + Collection newKeys = new HashSet<>(pressedKeys); + Collection releasedKeys = currentlyPressed; + newKeys.removeAll(releasedKeys); + releasedKeys.removeAll(pressedKeys); + + // Released Keys + if (!releasedKeys.isEmpty()) { +// AllPackets.channel.sendToServer(new LinkedControllerInputPacket(releasedKeys, false, lecternPos)); +// AllSoundEvents.CONTROLLER_CLICK.playAt(player.level, player.blockPosition(), 1f, .5f, true); + } + + // Newly Pressed Keys + if (!newKeys.isEmpty()) { + if (newKeys.contains(Integer.valueOf(5))) { + stopControlling(); + return; + } + +// AllPackets.channel.sendToServer(new LinkedControllerInputPacket(newKeys, true, lecternPos)); +// packetCooldown = PACKET_RATE; +// AllSoundEvents.CONTROLLER_CLICK.playAt(player.level, player.blockPosition(), 1f, .75f, true); + } + + // Keepalive Pressed Keys + if (packetCooldown == 0) { +// if (!pressedKeys.isEmpty()) { +// AllPackets.channel.sendToServer(new LinkedControllerInputPacket(pressedKeys, true, lecternPos)); +// packetCooldown = PACKET_RATE; +// } + } + + // TODO do this server side + if (!entity.control(controlsPos, pressedKeys, player)) { + stopControlling(); + return; + } + + currentlyPressed = pressedKeys; + controls.forEach(kb -> kb.setDown(false)); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsInteractionBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsInteractionBehaviour.java new file mode 100644 index 000000000..019c27a38 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsInteractionBehaviour.java @@ -0,0 +1,20 @@ +package com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls; + +import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.components.structureMovement.MovingInteractionBehaviour; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.player.Player; + +public class ControlsInteractionBehaviour extends MovingInteractionBehaviour { + + @Override + public boolean handlePlayerInteraction(Player player, InteractionHand activeHand, BlockPos localPos, + AbstractContraptionEntity contraptionEntity) { + if (player.level.isClientSide) + ControlsHandler.controllerClicked(contraptionEntity, localPos); + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsMovementBehaviour.java index 8b5f9eede..0523e228f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsMovementBehaviour.java @@ -1,9 +1,16 @@ package com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls; +import java.util.Collection; + import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices; +import com.simibubi.create.content.logistics.trains.entity.Carriage; +import com.simibubi.create.content.logistics.trains.entity.CarriageContraptionEntity; +import com.simibubi.create.foundation.utility.AnimationTickHolder; +import com.simibubi.create.foundation.utility.animation.LerpedFloat; +import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraftforge.api.distmarker.Dist; @@ -11,11 +18,38 @@ import net.minecraftforge.api.distmarker.OnlyIn; public class ControlsMovementBehaviour extends MovementBehaviour { + // TODO: this is specific to Carriage Contraptions - need to move this behaviour + // there + LerpedFloat steering = LerpedFloat.linear(); + LerpedFloat speed = LerpedFloat.linear(); + LerpedFloat equipAnimation = LerpedFloat.linear(); + + @Override + public void tick(MovementContext context) { + steering.tickChaser(); + speed.tickChaser(); + equipAnimation.tickChaser(); + super.tick(context); + } + @Override @OnlyIn(Dist.CLIENT) public void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld, ContraptionMatrices matrices, MultiBufferSource buffer) { - ControlsRenderer.render(context, renderWorld, matrices, buffer); + if (ControlsHandler.entityRef.get() == context.contraption.entity && ControlsHandler.controlsPos != null + && ControlsHandler.controlsPos.equals(context.localPos)) { + Collection pressed = ControlsHandler.currentlyPressed; + equipAnimation.chase(1, .2f, Chaser.EXP); + steering.chase((pressed.contains(3) ? 1 : 0) + (pressed.contains(2) ? -1 : 0), 0.2f, Chaser.EXP); + if (context.contraption.entity instanceof CarriageContraptionEntity car) { + Carriage carriage = car.getCarriage(); + speed.chase(Math.abs(carriage.train.speed), 0.2f, Chaser.EXP); + } + } else + equipAnimation.chase(0, .2f, Chaser.EXP); + float pt = AnimationTickHolder.getPartialTicks(context.world); + ControlsRenderer.render(context, renderWorld, matrices, buffer, equipAnimation.getValue(pt), speed.getValue(pt), + steering.getValue(pt)); } - + } 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 d33d989f4..b01423a36 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 @@ -1,8 +1,9 @@ package com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls; import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; +import com.jozufozu.flywheel.util.transform.MatrixTransformStack; +import com.mojang.blaze3d.vertex.PoseStack; 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; @@ -16,38 +17,43 @@ 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 { public static void render(MovementContext context, VirtualRenderWorld renderWorld, ContraptionMatrices matrices, - MultiBufferSource buffer) { + MultiBufferSource buffer, float equipAnimation, float firstLever, float secondLever) { BlockState state = context.state; Direction facing = state.getValue(ControlsBlock.FACING); SuperByteBuffer cover = CachedBufferer.partial(AllBlockPartials.TRAIN_CONTROLS_COVER, state); float hAngle = 180 + AngleHelper.horizontalAngle(facing); - cover.transform(matrices.getModel()) + PoseStack ms = matrices.getModel(); + cover.transform(ms) .centre() .rotateY(hAngle) .unCentre() .light(matrices.getWorld(), ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld)) .renderInto(matrices.getViewProjection(), buffer.getBuffer(RenderType.solid())); + double yOffset = Mth.lerp(equipAnimation * equipAnimation, -0.15f, 0.05f); + 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); + float vAngle = (float) Mth.clamp(first ? firstLever * 70 - 25 : secondLever * 15, -45, 45); SuperByteBuffer lever = CachedBufferer.partial(AllBlockPartials.TRAIN_CONTROLS_LEVER, state); - lever.transform(matrices.getModel()) - .centre() + ms.pushPose(); + new MatrixTransformStack(ms).centre() .rotateY(hAngle) - .rotateX(vAngle) + .translate(0, 0, 4 / 16f) + .rotateX(vAngle - 45) + .translate(0, yOffset, 0) + .rotateX(45) .unCentre() - .translate(first ? 0 : 6 / 16f, 0, 0) + .translate(0, -2 / 16f, -3 / 16f) + .translate(first ? 0 : 6 / 16f, 0, 0); + lever.transform(ms) .light(matrices.getWorld(), ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld)) .renderInto(matrices.getViewProjection(), buffer.getBuffer(RenderType.solid())); + ms.popPose(); } } diff --git a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerClientHandler.java b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerClientHandler.java index 1c3452d7f..75f68491d 100644 --- a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerClientHandler.java +++ b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerClientHandler.java @@ -18,12 +18,12 @@ import com.simibubi.create.foundation.item.TooltipHelper; import com.simibubi.create.foundation.networking.AllPackets; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.linked.LinkBehaviour; +import com.simibubi.create.foundation.utility.ControlsUtil; import com.simibubi.create.foundation.utility.Lang; import net.minecraft.ChatFormatting; import net.minecraft.client.KeyMapping; import net.minecraft.client.Minecraft; -import net.minecraft.client.Options; import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.player.LocalPlayer; import net.minecraft.core.BlockPos; @@ -43,24 +43,8 @@ public class LinkedControllerClientHandler { public static Collection currentlyPressed = new HashSet<>(); private static BlockPos lecternPos; private static BlockPos selectedLocation = BlockPos.ZERO; - private static Vector controls; - private static int packetCooldown; - public static Vector getControls() { - if (controls == null) { - Options gameSettings = Minecraft.getInstance().options; - controls = new Vector<>(6); - controls.add(gameSettings.keyUp); - controls.add(gameSettings.keyDown); - controls.add(gameSettings.keyLeft); - controls.add(gameSettings.keyRight); - controls.add(gameSettings.keyJump); - controls.add(gameSettings.keyShift); - } - return controls; - } - public static void toggleBindMode(BlockPos location) { if (MODE == Mode.IDLE) { MODE = Mode.BIND; @@ -100,7 +84,7 @@ public class LinkedControllerClientHandler { } protected static void onReset() { - getControls().forEach(kb -> kb.setDown(isActuallyPressed(kb))); + ControlsUtil.getControls().forEach(kb -> kb.setDown(ControlsUtil.isActuallyPressed(kb))); packetCooldown = 0; selectedLocation = BlockPos.ZERO; @@ -115,14 +99,6 @@ public class LinkedControllerClientHandler { LinkedControllerItemRenderer.resetButtons(); } - protected static boolean isActuallyPressed(KeyMapping kb) { - return InputConstants.isKeyDown(Minecraft.getInstance() - .getWindow() - .getWindow(), - kb.getKey() - .getValue()); - } - public static void tick() { LinkedControllerItemRenderer.tick(); @@ -169,10 +145,10 @@ public class LinkedControllerClientHandler { return; } - Vector controls = getControls(); + Vector controls = ControlsUtil.getControls(); Collection pressedKeys = new HashSet<>(); for (int i = 0; i < controls.size(); i++) { - if (isActuallyPressed(controls.get(i))) + if (ControlsUtil.isActuallyPressed(controls.get(i))) pressedKeys.add(i); } @@ -240,7 +216,7 @@ public class LinkedControllerClientHandler { tooltipScreen.init(mc, width1, height1); Object[] keys = new Object[6]; - Vector controls = getControls(); + Vector controls = ControlsUtil.getControls(); for (int i = 0; i < controls.size(); i++) { KeyMapping keyBinding = controls.get(i); keys[i] = keyBinding.getTranslatedKeyMessage() diff --git a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerScreen.java b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerScreen.java index 972b2815e..0bb791ace 100644 --- a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerScreen.java +++ b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerScreen.java @@ -13,6 +13,7 @@ import com.simibubi.create.foundation.gui.AllIcons; import com.simibubi.create.foundation.gui.container.AbstractSimiContainerScreen; import com.simibubi.create.foundation.gui.element.GuiGameElement; import com.simibubi.create.foundation.gui.widget.IconButton; +import com.simibubi.create.foundation.utility.ControlsUtil; import com.simibubi.create.foundation.utility.Lang; import net.minecraft.ChatFormatting; @@ -112,7 +113,7 @@ public class LinkedControllerScreen extends AbstractSimiContainerScreen(null); this.id = netIdGenerator.incrementAndGet(); - + bogey1.carriage = this; if (bogey2 != null) bogey2.carriage = this; @@ -59,7 +59,8 @@ public class Carriage { } public double travel(Level level, TrackGraph graph, double distance, - @Nullable Function control) { + Function forwardControl, + Function backwardControl) { Vec3 leadingAnchor = leadingBogey().anchorPosition; Vec3 trailingAnchor = trailingBogey().anchorPosition; boolean onTwoBogeys = isOnTwoBogeys(); @@ -86,14 +87,20 @@ public class Carriage { bogey.points.forEachWithContext((point, first) -> { TravellingPoint prevPoint = previous.getValue(); - ITrackSelector trackSelector = - prevPoint == null ? control == null ? point.random() : control.apply(point) - : point.follow(prevPoint); + TravellingPoint nextPoint = first ? bogey.points.getSecond() + : firstBogey && onTwoBogeys ? bogeys.getSecond().points.getFirst() : null; double correction = bogeyStress * (first ? leadingPointModifier : trailingPointModifier); double toMove = distanceMoved.getValue(); - double moved = point.travel(graph, toMove, trackSelector); - point.travel(graph, correction + bogeyCorrection, trackSelector); + + ITrackSelector frontTrackSelector = + prevPoint == null ? forwardControl.apply(point) : point.follow(prevPoint); + ITrackSelector backTrackSelector = + nextPoint == null ? backwardControl.apply(point) : point.follow(nextPoint); + + double moved = point.travel(graph, toMove, toMove > 0 ? frontTrackSelector : backTrackSelector); + point.travel(graph, correction + bogeyCorrection, + correction + bogeyCorrection > 0 ? frontTrackSelector : backTrackSelector); blocked |= point.blocked; distanceMoved.setValue(moved); @@ -201,9 +208,9 @@ public class Carriage { public Vec3 leadingCouplingAnchor; public Vec3 trailingCouplingAnchor; - + int derailAngle; - + public CarriageBogey(IBogeyBlock type, TravellingPoint point, TravellingPoint point2) { this.type = type; points = Couple.create(point, point2); @@ -223,11 +230,11 @@ public class Carriage { double diffZ = positionVec.z - coupledVec.z; float yRot = AngleHelper.deg(Mth.atan2(diffZ, diffX)) + 90; float xRot = AngleHelper.deg(Math.atan2(diffY, Math.sqrt(diffX * diffX + diffZ * diffZ))); - + if (carriage.train.derailed) yRot += derailAngle; - - wheelAngle.setValue((wheelAngle.getValue() - angleDiff) % 360); + + wheelAngle.setValue((wheelAngle.getValue() - angleDiff * Math.signum(carriage.train.speed)) % 360); pitch.setValue(xRot); yaw.setValue(-yRot); } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraption.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraption.java index f59fbef5d..d70f5e477 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraption.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraption.java @@ -8,6 +8,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.Con import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionLighter; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType; import com.simibubi.create.content.contraptions.components.structureMovement.NonStationaryLighter; +import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.ControlsBlock; import com.simibubi.create.content.logistics.trains.IBogeyBlock; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.NBTHelper; @@ -24,7 +25,10 @@ public class CarriageContraption extends Contraption { private Direction assemblyDirection; - private boolean controls; + private boolean forwardControls; + private boolean backwardControls; + private boolean sidewaysControls; + private int bogeys; private BlockPos secondBogeyPos; @@ -48,6 +52,8 @@ public class CarriageContraption extends Contraption { return false; if (bogeys > 2) throw new AssemblyException(Lang.translate("train_assembly.too_many_bogeys", bogeys)); + if (sidewaysControls) + throw new AssemblyException(Lang.translate("train_assembly.sideways_controls")); return true; } @@ -67,8 +73,15 @@ public class CarriageContraption extends Contraption { return Pair.of(new StructureBlockInfo(pos, blockState, null), null); } - if (AllBlocks.CONTROLS.has(blockState)) - controls = true; + if (AllBlocks.CONTROLS.has(blockState)) { + Direction facing = blockState.getValue(ControlsBlock.FACING); + if (facing.getAxis() != assemblyDirection.getAxis()) + sidewaysControls = true; + else if (facing == assemblyDirection) + forwardControls = true; + else + backwardControls = true; + } return super.capture(world, pos); } @@ -79,7 +92,8 @@ public class CarriageContraption extends Contraption { NBTHelper.writeEnum(tag, "AssemblyDirection", getAssemblyDirection()); if (spawnPacket) tag.putInt("CarriageId", carriage.id); - tag.putBoolean("Controls", hasControls()); + tag.putBoolean("FrontControls", forwardControls); + tag.putBoolean("BackControls", backwardControls); return tag; } @@ -88,7 +102,8 @@ public class CarriageContraption extends Contraption { assemblyDirection = NBTHelper.readEnum(nbt, "AssemblyDirection", Direction.class); if (spawnData) temporaryCarriageIdHolder = nbt.getInt("CarriageId"); - controls = nbt.getBoolean("Controls"); + forwardControls = nbt.getBoolean("FrontControls"); + backwardControls = nbt.getBoolean("BackControls"); super.readNBT(world, nbt, spawnData); } @@ -120,8 +135,12 @@ public class CarriageContraption extends Contraption { return carriage; } - public boolean hasControls() { - return controls; + public boolean hasForwardControls() { + return forwardControls; + } + + public boolean hasBackwardControls() { + return backwardControls; } public BlockPos getSecondBogeyPos() { 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 a2c637012..e6e28c434 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 @@ -1,14 +1,34 @@ package com.simibubi.create.content.logistics.trains.entity; +import java.util.Collection; + +import com.google.common.base.Strings; import com.simibubi.create.AllEntityTypes; import com.simibubi.create.Create; import com.simibubi.create.content.contraptions.components.structureMovement.OrientedContraptionEntity; +import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.ControlsBlock; +import com.simibubi.create.content.logistics.trains.entity.TravellingPoint.SteerDirection; +import com.simibubi.create.content.logistics.trains.management.GlobalStation; +import com.simibubi.create.foundation.utility.Color; +import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.VecHelper; +import net.minecraft.ChatFormatting; +import net.minecraft.client.Minecraft; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TextComponent; +import net.minecraft.util.Mth; import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; import net.minecraft.world.phys.Vec3; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.fml.DistExecutor; public class CarriageContraptionEntity extends OrientedContraptionEntity { @@ -30,16 +50,158 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity { return entity; } + @Override + public Component getContraptionName() { + Carriage carriage = getCarriage(); + if (carriage != null) + return carriage.train.name; + Component contraptionName = super.getContraptionName(); + return contraptionName; + } + + @Override + public boolean startControlling(BlockPos controlsLocalPos) { + Carriage carriage = getCarriage(); + if (carriage == null) + return false; + if (carriage.train.derailed) + return false; + + Train train = carriage.train; + if (train.runtime.getSchedule() != null && !train.runtime.paused) + train.status.manualControls(); + train.navigation.cancelNavigation(); + train.runtime.paused = true; + return true; + } + + double navDistanceTotal = 0; + + @Override + public boolean control(BlockPos controlsLocalPos, Collection heldControls, Player player) { + Carriage carriage = getCarriage(); + if (carriage == null) + return false; + if (carriage.train.derailed) + return false; + + StructureBlockInfo info = contraption.getBlocks() + .get(controlsLocalPos); + Direction initialOrientation = getInitialOrientation().getCounterClockWise(); + boolean inverted = false; + if (info != null && info.state.hasProperty(ControlsBlock.FACING)) + inverted = !info.state.getValue(ControlsBlock.FACING) + .equals(initialOrientation); + + int targetSpeed = 0; + if (heldControls.contains(0)) + targetSpeed++; + if (heldControls.contains(1)) + targetSpeed--; + + int targetSteer = 0; + if (heldControls.contains(2)) + targetSteer++; + if (heldControls.contains(3)) + targetSteer--; + + if (inverted) { + targetSpeed *= -1; +// targetSteer *= -1; + } + + 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); + return true; + } + + 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); + } + + if (currentStation == null && targetSpeed >= 0) { + Navigation nav = carriage.train.navigation; + if (nav.destination != null) { + if (!spaceDown) + nav.cancelNavigation(); + if (spaceDown) { + 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(0xff_91EA44, 0xff_FFC244, progress / 30f); + int targetColor = arrived ? 0xff_91EA44 : 0xff_ffffff; + player.displayClientMessage(greenComponent.withStyle(st -> st.withColor(mixedColor)) + .append(whiteComponent.withStyle(st -> st.withColor(targetColor))), true); + return true; + } + } + + GlobalStation lookAhead = nav.findNearestApproachable(); + if (lookAhead != null) { + if (spaceDown) { + nav.startNavigation(lookAhead, false); + navDistanceTotal = nav.distanceToDestination; + return true; + } + if (level.isClientSide) + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> displayApproachStationMessage(lookAhead)); + } else { + if (level.isClientSide) + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> this::cleanUpApproachStationMessage); + } + } + + carriage.train.manualSteer = + targetSteer < 0 ? SteerDirection.RIGHT : targetSteer > 0 ? SteerDirection.LEFT : SteerDirection.NONE; + carriage.train.targetSpeed = Train.topSpeed * targetSpeed; + if (inverted ^ targetSpeed < 0) + carriage.train.targetSpeed /= 8; + boolean counteringAcceleration = Math.abs(Math.signum(targetSpeed) - Math.signum(carriage.train.speed)) > 1.5f; + carriage.train.manualTick = true; + carriage.train.approachTargetSpeed(counteringAcceleration ? 2 : 1); + return true; + } + + boolean stationMessage = false; + + @OnlyIn(Dist.CLIENT) + private void displayApproachStationMessage(GlobalStation station) { + Minecraft instance = Minecraft.getInstance(); + instance.player.displayClientMessage(Lang.translate("contraption.controls.approach_station", + instance.options.keyJump.getTranslatedKeyMessage(), station.name), true); + stationMessage = true; + } + + @OnlyIn(Dist.CLIENT) + private void cleanUpApproachStationMessage() { + if (!stationMessage) + return; + Minecraft instance = Minecraft.getInstance(); + instance.player.displayClientMessage(new TextComponent(""), true); + stationMessage = false; + } + @Override protected void tickContraption() { if (!(contraption instanceof CarriageContraption)) return; - int id = ((CarriageContraption) contraption).temporaryCarriageIdHolder; - Carriage carriage = Create.RAILWAYS.carriageById.get(id); // TODO: thread breach + Carriage carriage = getCarriage(); if (carriage == null) { discard(); return; } + + tickActors(); + if (!level.isClientSide) return; @@ -61,6 +223,12 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity { } + public Carriage getCarriage() { + int id = ((CarriageContraption) contraption).temporaryCarriageIdHolder; + Carriage carriage = Create.RAILWAYS.carriageById.get(id); // TODO: thread breach + return carriage; + } + Vec3 derailParticleOffset = VecHelper.offsetRandomly(Vec3.ZERO, Create.RANDOM, 1.5f) .multiply(1, .25f, 1); diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraptionEntityRenderer.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraptionEntityRenderer.java index 3e20c82f3..8f2d7198a 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraptionEntityRenderer.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraptionEntityRenderer.java @@ -2,7 +2,6 @@ package com.simibubi.create.content.logistics.trains.entity; import com.jozufozu.flywheel.util.transform.MatrixTransformStack; import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.Create; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionEntityRenderer; import net.minecraft.client.renderer.MultiBufferSource; @@ -29,8 +28,7 @@ public class CarriageContraptionEntityRenderer extends ContraptionEntityRenderer MultiBufferSource buffers, int overlay) { super.render(entity, yaw, partialTicks, ms, buffers, overlay); - int id = ((CarriageContraption) entity.getContraption()).temporaryCarriageIdHolder; - Carriage carriage = Create.RAILWAYS.carriageById.get(id); + Carriage carriage = entity.getCarriage(); if (carriage == null) return; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/Navigation.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/Navigation.java index 3a7382a66..7a77d083a 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/Navigation.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/Navigation.java @@ -8,6 +8,9 @@ import java.util.Map; import java.util.Map.Entry; import java.util.PriorityQueue; import java.util.Set; +import java.util.function.BiPredicate; + +import org.apache.commons.lang3.mutable.MutableObject; import com.simibubi.create.content.logistics.trains.TrackEdge; import com.simibubi.create.content.logistics.trains.TrackGraph; @@ -18,7 +21,6 @@ import com.simibubi.create.content.logistics.trains.management.GlobalStation; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.Pair; -import net.minecraft.util.Mth; import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec3; @@ -64,15 +66,7 @@ public class Navigation { double brakingDistance = (train.speed * train.speed) / (2 * Train.acceleration); train.targetSpeed = distanceToDestination > brakingDistance ? Train.topSpeed : 0; - - if (Mth.equal(train.targetSpeed, train.speed)) - return; - - if (train.speed < train.targetSpeed) - train.speed = Math.min(train.speed + Train.acceleration, train.targetSpeed); - else if (train.speed > train.targetSpeed) - train.speed = Math.max(train.speed - Train.acceleration, train.targetSpeed); - + train.approachTargetSpeed(1); } public boolean isActive() { @@ -80,17 +74,20 @@ public class Navigation { } public ITrackSelector control(TravellingPoint mp) { - return (graph, list) -> { + if (destination == null) + return mp.steer(train.manualSteer, new Vec3(0, 1, 0)); + return (graph, pair) -> { if (!currentPath.isEmpty()) { TrackEdge target = currentPath.get(0); - for (Entry entry : list) { + for (Entry entry : pair.getSecond()) { if (entry.getValue() == target) { currentPath.remove(0); return entry; } } } - return list.get(0); + return pair.getSecond() + .get(0); }; } @@ -122,7 +119,7 @@ public class Navigation { if (this.destination == destination) return 0; - train.leave(); + train.leaveStation(); this.destination = destination; return distanceToDestination; } @@ -130,19 +127,103 @@ public class Navigation { private Pair> findPathTo(GlobalStation destination) { TrackGraph graph = train.graph; List path = new ArrayList<>(); - double distanceToDestination = 0; if (graph == null) return Pair.of(-1d, path); Couple target = destination.edgeLocation; - PriorityQueue, TrackEdge>>> frontier = - new PriorityQueue<>((p1, p2) -> Double.compare(p1.getFirst(), p2.getFirst())); + TravellingPoint leadingPoint = train.carriages.get(0) + .getLeadingPoint(); + TrackEdge initialEdge = leadingPoint.edge; + + MutableObject>> result = new MutableObject<>(Pair.of(-1d, path)); + + search((reachedVia, poll) -> { + double distance = poll.getFirst(); + Pair, TrackEdge> currentEntry = poll.getSecond(); + TrackEdge edge = currentEntry.getSecond(); + TrackNode node1 = currentEntry.getFirst() + .getFirst(); + TrackNode node2 = currentEntry.getFirst() + .getSecond(); + + TrackNodeLocation loc1 = node1.getLocation(); + TrackNodeLocation loc2 = node2.getLocation(); + if (!loc1.equals(target.getFirst()) || !loc2.equals(target.getSecond())) + return false; + + Pair backTrack = reachedVia.get(edge); + TrackEdge toReach = edge; + while (backTrack != null && toReach != initialEdge) { + if (backTrack.getFirst()) + path.add(0, toReach); + toReach = backTrack.getSecond(); + backTrack = reachedVia.get(backTrack.getSecond()); + } + + double distanceToDestination = distance; + double position = edge.getLength(node1, node2) - destination.position; + distanceToDestination -= position; + result.setValue(Pair.of(distanceToDestination, path)); + return true; + }, Double.MAX_VALUE); + + return result.getValue(); + } + + public GlobalStation findNearestApproachable() { + TrackGraph graph = train.graph; + if (graph == null) + return null; + + MutableObject result = new MutableObject<>(null); + double minDistance = .75f * (train.speed * train.speed) / (2 * Train.acceleration); + double maxDistance = Math.max(32, 1.5f * (train.speed * train.speed) / (2 * Train.acceleration)); + + search((reachedVia, poll) -> { + double distance = poll.getFirst(); + if (distance < minDistance) + return false; + + Pair, TrackEdge> currentEntry = poll.getSecond(); + TrackEdge edge = currentEntry.getSecond(); + TrackNode node1 = currentEntry.getFirst() + .getFirst(); + TrackNode node2 = currentEntry.getFirst() + .getSecond(); + + for (GlobalStation globalStation : graph.getStations()) { + Couple target = globalStation.edgeLocation; + TrackNodeLocation loc1 = node1.getLocation(); + TrackNodeLocation loc2 = node2.getLocation(); + if (!loc1.equals(target.getFirst()) || !loc2.equals(target.getSecond())) + continue; + double position = edge.getLength(node1, node2) - globalStation.position; + if (distance - position < minDistance) + continue; + result.setValue(globalStation); + return true; + } + + return false; + }, maxDistance); + + return result.getValue(); + } + + public void search( + BiPredicate>, Pair, TrackEdge>>> condition, + double maxDistance) { + TrackGraph graph = train.graph; + if (graph == null) + return; TravellingPoint leadingPoint = train.carriages.get(0) .getLeadingPoint(); Set visited = new HashSet<>(); Map> reachedVia = new IdentityHashMap<>(); + PriorityQueue, TrackEdge>>> frontier = + new PriorityQueue<>((p1, p2) -> Double.compare(p1.getFirst(), p2.getFirst())); TrackEdge initialEdge = leadingPoint.edge; TrackNode initialNode1 = leadingPoint.node1; @@ -153,39 +234,19 @@ public class Navigation { while (!frontier.isEmpty()) { Pair, TrackEdge>> poll = frontier.poll(); double distance = poll.getFirst(); + if (distance > maxDistance) + continue; + Pair, TrackEdge> currentEntry = poll.getSecond(); - List> validTargets = new ArrayList<>(); TrackEdge edge = currentEntry.getSecond(); TrackNode node1 = currentEntry.getFirst() .getFirst(); TrackNode node2 = currentEntry.getFirst() .getSecond(); + if (condition.test(reachedVia, poll)) + return; - TrackNodeLocation loc1 = node1.getLocation(); - TrackNodeLocation loc2 = node2.getLocation(); - boolean enteringBackward = loc2.equals(target.getFirst()) && loc1.equals(target.getSecond()); - boolean enteringForward = loc1.equals(target.getFirst()) && loc2.equals(target.getSecond()); - - if (enteringForward || train.doubleEnded && enteringBackward) { - Pair backTrack = reachedVia.get(edge); - TrackEdge toReach = edge; - while (backTrack != null && toReach != initialEdge) { - if (backTrack.getFirst()) - path.add(0, toReach); - toReach = backTrack.getSecond(); - backTrack = reachedVia.get(backTrack.getSecond()); - } - - distanceToDestination = distance; - double position = destination.position; - if (enteringForward) - position = edge.getLength(node1, node2) - position; - else - distanceToDestination += train.getTotalLength() + 2; - distanceToDestination -= position; - return Pair.of(distanceToDestination, path); - } - + List> validTargets = new ArrayList<>(); for (Entry entry : graph.getConnectionsFrom(node2) .entrySet()) { TrackNode newNode = entry.getKey(); @@ -210,8 +271,6 @@ public class Navigation { Pair.of(Couple.create(node2, newNode), newEdge))); } } - - return Pair.of(-1d, path); } } 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 73c15c9a1..2abf9d0d0 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 @@ -21,6 +21,7 @@ import com.simibubi.create.CreateClient; import com.simibubi.create.content.logistics.trains.TrackGraph; 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.GlobalStation; import com.simibubi.create.content.logistics.trains.management.GraphLocation; import com.simibubi.create.content.logistics.trains.management.ScheduleRuntime; @@ -56,6 +57,9 @@ public class Train { public Component name; public TrainStatus status; + public SteerDirection manualSteer; + public boolean manualTick; + public UUID currentStation; public boolean heldForAssembly; @@ -85,12 +89,14 @@ public class Train { Create.RAILWAYS.carriageById.put(c.id, c); }); - doubleEnded = carriages.size() > 1 && carriages.get(carriages.size() - 1).contraption.hasControls(); + doubleEnded = carriages.stream() + .anyMatch(c -> c.contraption.hasBackwardControls()); navigation = new Navigation(this, graph); runtime = new ScheduleRuntime(this); heldForAssembly = true; migratingPoints = new ArrayList<>(); currentStation = null; + manualSteer = SteerDirection.NONE; } public void tick(Level level) { @@ -105,11 +111,13 @@ public class Train { runtime.tick(level); navigation.tick(level); - if (navigation.destination == null && speed > 0) { - speed -= acceleration; - if (speed <= 0) - speed = 0; + if (!manualTick && navigation.destination == null && speed != 0) { + if (speed > 0) + speed = Math.max(speed - acceleration, 0); + else + speed = Math.min(speed + acceleration, 0); } + manualTick = false; if (derailed) { speed /= 3f; @@ -145,12 +153,20 @@ public class Train { for (int i = 0; i < carriages.size(); i++) { double leadingStress = i == 0 ? 0 : stress[i - 1] * leadingModifier; double trailingStress = i == stress.length ? 0 : stress[i] * trailingModifier; - Carriage carriage = carriages.get(i); - TravellingPoint toFollow = previous; - Function control = - previous == null ? navigation::control : mp -> mp.follow(toFollow); - double actualDistance = carriage.travel(level, graph, distance + leadingStress + trailingStress, control); + + TravellingPoint toFollowForward = previous; + TravellingPoint toFollowBackward = i == carriages.size() - 1 ? null + : carriages.get(i + 1) + .getLeadingPoint(); + + Function forwardControl = + toFollowForward == null ? navigation::control : mp -> mp.follow(toFollowForward); + Function backwardControl = + toFollowBackward == null ? navigation::control : mp -> mp.follow(toFollowBackward); + + double actualDistance = carriage.travel(level, graph, distance + leadingStress + trailingStress, + forwardControl, backwardControl); blocked |= carriage.blocked; if (i == 0) { @@ -165,7 +181,7 @@ public class Train { navigation.cancelNavigation(); runtime.tick(level); status.endOfTrack(); - } else if (speed > 0) + } else if (speed != 0) status.trackOK(); if (navigation.destination != null) { @@ -376,7 +392,7 @@ public class Train { return length; } - public void leave() { + public void leaveStation() { GlobalStation currentStation = getCurrentStation(); if (currentStation == null) return; @@ -411,4 +427,15 @@ public class Train { } } + public void approachTargetSpeed(float accelerationMod) { + if (Mth.equal(targetSpeed, speed)) + return; + if (manualTick) + leaveStation(); + if (speed < targetSpeed) + speed = Math.min(speed + Train.acceleration * accelerationMod, targetSpeed); + else if (speed > targetSpeed) + speed = Math.max(speed - Train.acceleration * accelerationMod, targetSpeed); + } + } 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 e67b42f52..898e7bb4f 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 @@ -188,7 +188,7 @@ public class TrainRelocator { }); train.status.successfulMigration(); - train.leave(); + train.leaveStation(); return true; } @@ -293,8 +293,7 @@ public class TrainRelocator { 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 + Carriage carriage = carriageContraptionEntity.getCarriage(); 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 cf3be4f2c..b0592e50e 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 @@ -36,6 +36,10 @@ public class TrainStatus { displayInformation("Navigation succeeded", true); navigation = false; } + + public void manualControls() { + displayInformation("Schedule paused for manual controls", true); + } public void failedMigration() { 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 7ad7aa39b..92fd2dcd0 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 @@ -13,6 +13,7 @@ import com.simibubi.create.content.logistics.trains.TrackEdge; import com.simibubi.create.content.logistics.trains.TrackGraph; import com.simibubi.create.content.logistics.trains.TrackNode; import com.simibubi.create.content.logistics.trains.management.GraphLocation; +import com.simibubi.create.foundation.utility.Pair; import net.minecraft.world.phys.Vec3; @@ -34,7 +35,7 @@ public class TravellingPoint { } public static interface ITrackSelector - extends BiFunction>, Entry> { + extends BiFunction>>, Entry> { }; public TravellingPoint(TrackNode node1, TrackNode node2, TrackEdge edge, double position) { @@ -45,15 +46,20 @@ public class TravellingPoint { } public ITrackSelector random() { - return (graph, validTargets) -> validTargets.get(Create.RANDOM.nextInt(validTargets.size())); + return (graph, pair) -> pair.getSecond() + .get(Create.RANDOM.nextInt(pair.getSecond() + .size())); } public ITrackSelector follow(TravellingPoint other) { - return (graph, validTargets) -> { - TrackNode target = other.node1; + return (graph, pair) -> { + List> validTargets = pair.getSecond(); + boolean forward = pair.getFirst(); + TrackNode target = forward ? other.node1 : other.node2; + TrackNode secondary = forward ? other.node2 : other.node1; for (Entry entry : validTargets) - if (entry.getKey() == target || entry.getKey() == other.node2) + if (entry.getKey() == target || entry.getKey() == secondary) return entry; Vector>> frontiers = new Vector<>(validTargets.size()); @@ -99,7 +105,9 @@ public class TravellingPoint { } public ITrackSelector steer(SteerDirection direction, Vec3 upNormal) { - return (graph, validTargets) -> { + return (graph, pair) -> { + List> validTargets = pair.getSecond(); + boolean forward = pair.getFirst(); double closest = Double.MAX_VALUE; Entry best = null; @@ -108,7 +116,7 @@ public class TravellingPoint { Vec3 entryTrajectory = entry.getValue() .getDirection(node2, entry.getKey(), true); Vec3 normal = trajectory.cross(upNormal); - double dot = normal.dot(entryTrajectory); + double dot = normal.dot(entryTrajectory) * (forward ? 1 : -1); double diff = Math.abs(direction.targetDot - dot); if (diff > closest) continue; @@ -136,43 +144,86 @@ public class TravellingPoint { double currentT = position / edgeLength; double incrementT = edge.incrementT(node1, node2, currentT, distance); position = incrementT * edgeLength; - List> validTargets = new ArrayList<>(); - while (position > edgeLength) { - validTargets.clear(); - for (Entry entry : graph.getConnectionsFrom(node2) - .entrySet()) { - TrackNode newNode = entry.getKey(); - if (newNode == node1) - continue; + if (distance > 0) { + // Moving forward + while (position > edgeLength) { + validTargets.clear(); - TrackEdge newEdge = entry.getValue(); - Vec3 currentDirection = edge.getDirection(node1, node2, false); - Vec3 newDirection = newEdge.getDirection(node2, newNode, true); - if (currentDirection.dot(newDirection) < 0) - continue; + for (Entry entry : graph.getConnectionsFrom(node2) + .entrySet()) { + TrackNode newNode = entry.getKey(); + if (newNode == node1) + continue; - validTargets.add(entry); + TrackEdge newEdge = entry.getValue(); + Vec3 currentDirection = edge.getDirection(node1, node2, false); + Vec3 newDirection = newEdge.getDirection(node2, newNode, true); + if (currentDirection.dot(newDirection) < 0) + continue; + + validTargets.add(entry); + } + + if (validTargets.isEmpty()) { + traveled -= position - edgeLength; + position = edgeLength; + blocked = true; + break; + } + + Entry entry = validTargets.size() == 1 ? validTargets.get(0) + : trackSelector.apply(graph, Pair.of(true, validTargets)); + + node1 = node2; + node2 = entry.getKey(); + edge = entry.getValue(); + position -= edgeLength; + edgeLength = edge.getLength(node1, node2); } - if (validTargets.isEmpty()) { - traveled -= position - edgeLength; - position = edgeLength; - blocked = true; - break; + } else { + // Moving backwards + while (position < 0) { + validTargets.clear(); + + for (Entry entry : graph.getConnectionsFrom(node1) + .entrySet()) { + TrackNode newNode = entry.getKey(); + if (newNode == node2) + continue; + + TrackEdge newEdge = graph.getConnectionsFrom(newNode) + .get(node1); + Vec3 currentDirection = edge.getDirection(node1, node2, true); + Vec3 newDirection = newEdge.getDirection(newNode, node1, false); + if (currentDirection.dot(newDirection) < 0) + continue; + + validTargets.add(entry); + } + + if (validTargets.isEmpty()) { + traveled -= position; + position = 0; + blocked = true; + break; + } + + Entry entry = validTargets.size() == 1 ? validTargets.get(0) + : trackSelector.apply(graph, Pair.of(false, validTargets)); + + node2 = node1; + node1 = entry.getKey(); + edge = graph.getConnectionsFrom(node1) + .get(node2); + edgeLength = edge.getLength(node1, node2); + position += edgeLength; } - Entry entry = - validTargets.size() == 1 ? validTargets.get(0) : trackSelector.apply(graph, validTargets); - - node1 = node2; - node2 = entry.getKey(); - edge = entry.getValue(); - position -= edgeLength; - edgeLength = edge.getLength(node1, node2); } - + return traveled; } 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 74c9b0588..00888f1e7 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 @@ -414,6 +414,7 @@ public class StationTileEntity extends SmartTileEntity { List contraptions = new ArrayList<>(); List carriages = new ArrayList<>(); List spacing = new ArrayList<>(); + boolean atLeastOneForwardControls = false; for (int bogeyIndex = 0; bogeyIndex < bogeyCount; bogeyIndex++) { int pointIndex = bogeyIndex * 2; @@ -425,6 +426,7 @@ public class StationTileEntity extends SmartTileEntity { try { boolean success = contraption.assemble(level, bogeyPosOffset.relative(assemblyDirection, bogeyLocations[bogeyIndex] + 1)); + atLeastOneForwardControls |= contraption.hasForwardControls(); if (!success) { exception(new AssemblyException(Lang.translate("train_assembly.nothing_attached", bogeyIndex + 1)), -1); @@ -467,6 +469,11 @@ public class StationTileEntity extends SmartTileEntity { carriages.add(carriage); } + if (!atLeastOneForwardControls) { + exception(new AssemblyException(Lang.translate("train_assembly.no_controls")), -1); + return; + } + for (CarriageContraption contraption : contraptions) { contraption.removeBlocksFromWorld(level, BlockPos.ZERO); contraption.expandBoundsAroundAxis(Axis.Y); diff --git a/src/main/java/com/simibubi/create/events/ClientEvents.java b/src/main/java/com/simibubi/create/events/ClientEvents.java index 940992791..e951339d0 100644 --- a/src/main/java/com/simibubi/create/events/ClientEvents.java +++ b/src/main/java/com/simibubi/create/events/ClientEvents.java @@ -15,6 +15,7 @@ import com.simibubi.create.content.contraptions.components.fan.AirCurrent; import com.simibubi.create.content.contraptions.components.flywheel.engine.EngineBlock; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionHandler; import com.simibubi.create.content.contraptions.components.structureMovement.chassis.ChassisRangeDisplay; +import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.ControlsHandler; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingHandlerClient; import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingPhysics; @@ -105,6 +106,7 @@ public class ClientEvents { Level world = Minecraft.getInstance().level; if (event.phase == Phase.START) { LinkedControllerClientHandler.tick(); + ControlsHandler.tick(); AirCurrent.tickClientPlayerSounds(); return; } diff --git a/src/main/java/com/simibubi/create/foundation/utility/ControlsUtil.java b/src/main/java/com/simibubi/create/foundation/utility/ControlsUtil.java new file mode 100644 index 000000000..643d781c0 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/utility/ControlsUtil.java @@ -0,0 +1,37 @@ +package com.simibubi.create.foundation.utility; + +import java.util.Vector; + +import com.mojang.blaze3d.platform.InputConstants; + +import net.minecraft.client.KeyMapping; +import net.minecraft.client.Minecraft; +import net.minecraft.client.Options; + +public class ControlsUtil { + + private static Vector standardControls; + + public static Vector getControls() { + if (standardControls == null) { + Options gameSettings = Minecraft.getInstance().options; + standardControls = new Vector<>(6); + standardControls.add(gameSettings.keyUp); + standardControls.add(gameSettings.keyDown); + standardControls.add(gameSettings.keyLeft); + standardControls.add(gameSettings.keyRight); + standardControls.add(gameSettings.keyJump); + standardControls.add(gameSettings.keyShift); + } + return standardControls; + } + + public static boolean isActuallyPressed(KeyMapping kb) { + return InputConstants.isKeyDown(Minecraft.getInstance() + .getWindow() + .getWindow(), + kb.getKey() + .getValue()); + } + +} diff --git a/src/main/resources/assets/create/lang/default/interface.json b/src/main/resources/assets/create/lang/default/interface.json index 048e5294f..caeaa5141 100644 --- a/src/main/resources/assets/create/lang/default/interface.json +++ b/src/main/resources/assets/create/lang/default/interface.json @@ -627,6 +627,8 @@ "create.train_assembly.not_connected_in_order": "Bogeys are not connected in order", "create.train_assembly.single_bogey_carriage": "This Bogey type cannot support a carriage on its own", "create.train_assembly.nothing_attached": "No structure attached to Bogey %1$s", + "create.train_assembly.no_controls": "At least one forward-facing controls block needs to be mounted on the train", + "create.train_assembly.sideways_controls": "A mounted controls block is facing sideways", "create.track_target.set": "Targeted track selected", "create.track_target.success": "Successfully bound to targeted track", @@ -643,6 +645,10 @@ "create.train.relocate.invalid": "Cannot relocate Train to this Track", "create.train.relocate.too_far": "Cannot relocate Train this far away", + "create.contraption.controls.start_controlling": "Now controlling: %1$s", + "create.contraption.controls.stop_controlling": "Stopped controlling contraption", + "create.contraption.controls.approach_station": "Hold %1$s to approach %2$s", + "create.gui.config.overlay1": "Hi :)", "create.gui.config.overlay2": "This is a sample overlay", "create.gui.config.overlay3": "Click or drag with your mouse", diff --git a/src/main/resources/assets/create/models/block/controls/block_closed.json b/src/main/resources/assets/create/models/block/controls/block_closed.json index faa53ee58..d5eb71a38 100644 --- a/src/main/resources/assets/create/models/block/controls/block_closed.json +++ b/src/main/resources/assets/create/models/block/controls/block_closed.json @@ -3,32 +3,53 @@ "texture_size": [32, 32], "textures": { "0": "create:block/brass_casing_belt", - "1": "create:block/brass_block", "3": "create:block/brass_funnel_plating", + "4": "create:block/blaze_burner_side", + "5": "create:block/blaze_heater_brazier", "particle": "create:block/brass_casing" }, "elements": [ { "from": [0, 0, 4], - "to": [16, 8, 16], + "to": [16, 4, 8], "faces": { - "north": {"uv": [8, 8.5, 16, 12.5], "texture": "#0"}, - "east": {"uv": [8, 8.5, 14, 12.5], "texture": "#0"}, - "south": {"uv": [8, 8.5, 16, 12.5], "texture": "#0"}, - "west": {"uv": [10, 8.5, 16, 12.5], "texture": "#0"}, - "up": {"uv": [9, 1, 15, 9], "rotation": 90, "texture": "#3"}, - "down": {"uv": [0, 2, 16, 14], "texture": "#1"} + "north": {"uv": [12, 0, 16, 16], "rotation": 90, "texture": "#4"}, + "east": {"uv": [12, 0, 16, 4], "rotation": 90, "texture": "#4"}, + "west": {"uv": [12, 12, 16, 16], "rotation": 90, "texture": "#4"}, + "up": {"uv": [8, 0, 16, 2], "texture": "#5"}, + "down": {"uv": [6, 8, 8, 16], "rotation": 90, "texture": "#5"} } }, { - "from": [0, 8, 6], + "from": [0, 0, 8], + "to": [8, 6, 16], + "faces": { + "north": {"uv": [2, 5, 6, 8], "texture": "#5"}, + "south": {"uv": [2, 5, 6, 8], "texture": "#5"}, + "west": {"uv": [2, 5, 6, 8], "texture": "#5"}, + "down": {"uv": [0, 8, 4, 11], "texture": "#5"} + } + }, + { + "from": [8, 0, 8], + "to": [16, 6, 16], + "faces": { + "north": {"uv": [2, 5, 6, 8], "texture": "#5"}, + "east": {"uv": [2, 5, 6, 8], "texture": "#5"}, + "south": {"uv": [2, 5, 6, 8], "texture": "#5"}, + "down": {"uv": [4, 8, 8, 11], "texture": "#5"} + } + }, + { + "from": [0, 6, 6], "to": [16, 14, 16], "faces": { - "north": {"uv": [11, 1, 14, 9], "rotation": 90, "texture": "#3"}, - "east": {"uv": [7, 0, 16, 6], "texture": "#1"}, - "south": {"uv": [2, 0, 14, 6], "texture": "#1"}, - "west": {"uv": [0, 0, 10, 6], "texture": "#1"}, - "up": {"uv": [9, 1, 14, 9], "rotation": 270, "texture": "#3"} + "north": {"uv": [10, 1, 14, 9], "rotation": 270, "texture": "#3"}, + "east": {"uv": [3, 0, 8, 4], "texture": "#0"}, + "south": {"uv": [8, 0, 16, 4], "texture": "#0"}, + "west": {"uv": [0, 0, 5, 4], "texture": "#0"}, + "up": {"uv": [9, 1, 14, 9], "rotation": 270, "texture": "#3"}, + "down": {"uv": [10, 1, 15, 9], "rotation": 270, "texture": "#3"} } } ], @@ -37,7 +58,7 @@ "name": "closed", "origin": [0, 0, 0], "color": 0, - "children": [0, 1] + "children": [0, 1, 2, 3] } ] } \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/controls/block_open.json b/src/main/resources/assets/create/models/block/controls/block_open.json index 24f7dd6fd..1beedf917 100644 --- a/src/main/resources/assets/create/models/block/controls/block_open.json +++ b/src/main/resources/assets/create/models/block/controls/block_open.json @@ -6,59 +6,88 @@ "1": "create:block/brass_block", "2": "create:block/brass_funnel_back", "3": "create:block/brass_funnel_plating", + "5": "create:block/blaze_burner_side", + "6": "create:block/blaze_heater_brazier", "particle": "create:block/brass_casing" }, "elements": [ { - "from": [0, 0, 4], - "to": [16, 8, 16], - "faces": { - "north": {"uv": [8, 8.5, 16, 12.5], "texture": "#0"}, - "east": {"uv": [8, 8.5, 14, 12.5], "texture": "#0"}, - "south": {"uv": [8, 8.5, 16, 12.5], "texture": "#0"}, - "west": {"uv": [10, 8.5, 16, 12.5], "texture": "#0"}, - "up": {"uv": [9, 1, 15, 9], "rotation": 90, "texture": "#3"}, - "down": {"uv": [0, 2, 16, 14], "texture": "#1"} - } - }, - { - "from": [14, 8, 6], + "from": [14, 6, 6], "to": [16, 14, 16], "faces": { - "north": {"uv": [11, 8, 14, 9], "rotation": 90, "texture": "#3"}, - "east": {"uv": [7, 0, 16, 6], "texture": "#1"}, - "south": {"uv": [11, 0, 13, 6], "texture": "#1"}, + "north": {"uv": [10, 8, 14, 9], "rotation": 90, "texture": "#3"}, + "east": {"uv": [7, 0, 16, 8], "texture": "#particle"}, + "south": {"uv": [15, 0, 16, 4], "texture": "#0"}, "west": {"uv": [0, 0, 10, 6], "texture": "#1"}, - "up": {"uv": [9, 8, 14, 9], "rotation": 270, "texture": "#3"} + "up": {"uv": [9, 8, 14, 9], "rotation": 270, "texture": "#3"}, + "down": {"uv": [10, 8, 15, 9], "rotation": 270, "texture": "#3"} } }, { - "from": [2, 8, 14], + "from": [2, 6, 14], "to": [14, 14, 16], "faces": { "north": {"uv": [2, 0, 14, 6], "texture": "#1"}, - "south": {"uv": [3, 0, 12, 6], "texture": "#1"}, + "south": {"uv": [9, 0, 15, 4], "texture": "#0"}, "up": {"uv": [10, 1, 14, 2], "rotation": 180, "texture": "#3"} } }, { - "from": [0, 8, 6], + "from": [0, 6, 6], "to": [2, 14, 16], "rotation": {"angle": 0, "axis": "y", "origin": [16, 0, 0]}, "faces": { - "north": {"uv": [11, 9, 14, 8], "rotation": 90, "texture": "#3"}, + "north": {"uv": [10, 9, 14, 8], "rotation": 90, "texture": "#3"}, "east": {"uv": [10, 0, 0, 6], "texture": "#1"}, - "south": {"uv": [4, 0, 2, 6], "texture": "#1"}, - "west": {"uv": [16, 0, 7, 6], "texture": "#1"}, - "up": {"uv": [9, 9, 14, 8], "rotation": 270, "texture": "#3"} + "south": {"uv": [9, 0, 8, 4], "texture": "#0"}, + "west": {"uv": [16, 0, 7, 8], "texture": "#particle"}, + "up": {"uv": [9, 9, 14, 8], "rotation": 270, "texture": "#3"}, + "down": {"uv": [10, 9, 15, 8], "rotation": 270, "texture": "#3"} } }, { - "from": [2, 8, 7], + "from": [2, 6, 7], "to": [14, 13, 14], "faces": { - "north": {"uv": [0, 8, 2.5, 14], "rotation": 270, "texture": "#2"}, - "up": {"uv": [2.5, 8, 6, 14], "rotation": 90, "texture": "#2"} + "north": {"uv": [0, 8, 3.5, 14], "rotation": 270, "texture": "#2"}, + "up": {"uv": [2.5, 8, 6, 14], "rotation": 90, "texture": "#2"}, + "down": {"uv": [2.5, 8, 6, 14], "rotation": 90, "texture": "#2"} + } + }, + { + "from": [0, 0, 8], + "to": [8, 6, 16], + "faces": { + "north": {"uv": [2, 5, 6, 8], "texture": "#6"}, + "east": {"uv": [0, 0, 0, 0], "texture": "#6"}, + "south": {"uv": [2, 5, 6, 8], "texture": "#6"}, + "west": {"uv": [2, 5, 6, 8], "texture": "#6"}, + "up": {"uv": [0, 0, 0, 0], "texture": "#6"}, + "down": {"uv": [0, 8, 4, 11], "texture": "#6"} + } + }, + { + "from": [8, 0, 8], + "to": [16, 6, 16], + "faces": { + "north": {"uv": [2, 5, 6, 8], "texture": "#6"}, + "east": {"uv": [2, 5, 6, 8], "texture": "#6"}, + "south": {"uv": [2, 5, 6, 8], "texture": "#6"}, + "west": {"uv": [0, 0, 0, 0], "texture": "#6"}, + "up": {"uv": [0, 0, 0, 0], "texture": "#6"}, + "down": {"uv": [4, 8, 8, 11], "texture": "#6"} + } + }, + { + "from": [0, 0, 4], + "to": [16, 4, 8], + "faces": { + "north": {"uv": [12, 0, 16, 16], "rotation": 90, "texture": "#5"}, + "east": {"uv": [12, 0, 16, 4], "rotation": 90, "texture": "#5"}, + "south": {"uv": [0, 0, 0, 0], "rotation": 90, "texture": "#6"}, + "west": {"uv": [12, 12, 16, 16], "rotation": 90, "texture": "#5"}, + "up": {"uv": [8, 0, 16, 2], "texture": "#6"}, + "down": {"uv": [6, 8, 8, 16], "rotation": 90, "texture": "#6"} } } ], @@ -67,7 +96,10 @@ "name": "open", "origin": [0, 0, 0], "color": 0, - "children": [0, 1, 2, 3, 4] - } + "children": [0, 1, 2, 3] + }, + 4, + 5, + 6 ] } \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/controls/item.json b/src/main/resources/assets/create/models/block/controls/item.json index 85fa1fe58..cfbf86c45 100644 --- a/src/main/resources/assets/create/models/block/controls/item.json +++ b/src/main/resources/assets/create/models/block/controls/item.json @@ -7,85 +7,12 @@ "2": "create:block/brass_funnel_back", "3": "create:block/brass_funnel_plating", "5": "block/lever", - "7": "create:block/chute" + "6": "create:block/blaze_heater_brazier", + "7": "create:block/chute", + "1_5": "create:block/blaze_burner_side", + "particle": "create:block/brass_casing" }, "elements": [ - { - "from": [0, 0, 4], - "to": [16, 8, 16], - "faces": { - "north": {"uv": [8, 8.5, 16, 12.5], "texture": "#0"}, - "east": {"uv": [8, 8.5, 14, 12.5], "texture": "#0"}, - "south": {"uv": [8, 8.5, 16, 12.5], "texture": "#0"}, - "west": {"uv": [10, 8.5, 16, 12.5], "texture": "#0"}, - "up": {"uv": [9, 1, 15, 9], "rotation": 90, "texture": "#3"}, - "down": {"uv": [0, 2, 16, 14], "texture": "#1"} - } - }, - { - "from": [14, 8, 6], - "to": [16, 14, 16], - "faces": { - "north": {"uv": [11, 8, 14, 9], "rotation": 90, "texture": "#3"}, - "east": {"uv": [7, 0, 16, 6], "texture": "#1"}, - "south": {"uv": [11, 0, 13, 6], "texture": "#1"}, - "west": {"uv": [0, 0, 10, 6], "texture": "#1"}, - "up": {"uv": [9, 8, 14, 9], "rotation": 270, "texture": "#3"} - } - }, - { - "from": [2, 8, 14], - "to": [14, 14, 16], - "faces": { - "north": {"uv": [2, 0, 14, 6], "texture": "#1"}, - "south": {"uv": [3, 0, 12, 6], "texture": "#1"}, - "up": {"uv": [10, 1, 14, 2], "rotation": 180, "texture": "#3"} - } - }, - { - "from": [0, 8, 6], - "to": [2, 14, 16], - "rotation": {"angle": 0, "axis": "y", "origin": [16, 0, 0]}, - "faces": { - "north": {"uv": [11, 9, 14, 8], "rotation": 90, "texture": "#3"}, - "east": {"uv": [10, 0, 0, 6], "texture": "#1"}, - "south": {"uv": [4, 0, 2, 6], "texture": "#1"}, - "west": {"uv": [16, 0, 7, 6], "texture": "#1"}, - "up": {"uv": [9, 9, 14, 8], "rotation": 270, "texture": "#3"} - } - }, - { - "from": [2, 8, 7], - "to": [14, 13, 14], - "faces": { - "north": {"uv": [0, 8, 2.5, 14], "rotation": 270, "texture": "#2"}, - "up": {"uv": [2.5, 8, 6, 14], "rotation": 90, "texture": "#2"} - } - }, - { - "from": [6, 7.25, 6.75], - "to": [10, 13.25, 14.75], - "faces": { - "north": {"uv": [10.5, 6, 13.5, 8], "rotation": 270, "texture": "#7"}, - "up": {"uv": [10, 6, 14, 8], "rotation": 90, "texture": "#7"} - } - }, - { - "from": [0, 7.25, 6.75], - "to": [4, 13.25, 14.75], - "faces": { - "north": {"uv": [10.5, 6, 13.5, 8], "rotation": 270, "texture": "#7"}, - "up": {"uv": [10, 6, 14, 8], "rotation": 90, "texture": "#7"} - } - }, - { - "from": [12, 7.25, 6.75], - "to": [16, 13.25, 14.75], - "faces": { - "north": {"uv": [10.5, 6, 13.5, 8], "rotation": 270, "texture": "#7"}, - "up": {"uv": [10, 6, 14, 8], "rotation": 90, "texture": "#7"} - } - }, { "from": [4, 9, -1], "to": [6, 11, 9], @@ -109,6 +36,109 @@ "up": {"uv": [7, 6, 9, 16], "texture": "#5"}, "down": {"uv": [7, 6, 9, 16], "rotation": 180, "texture": "#5"} } + }, + { + "from": [14, 6, 6], + "to": [16, 14, 16], + "faces": { + "north": {"uv": [10, 8, 14, 9], "rotation": 90, "texture": "#3"}, + "east": {"uv": [7, 0, 16, 8], "texture": "#particle"}, + "south": {"uv": [15, 0, 16, 4], "texture": "#0"}, + "west": {"uv": [0, 0, 10, 6], "texture": "#1"}, + "up": {"uv": [9, 8, 14, 9], "rotation": 270, "texture": "#3"}, + "down": {"uv": [10, 8, 15, 9], "rotation": 270, "texture": "#3"} + } + }, + { + "from": [2, 6, 14], + "to": [14, 14, 16], + "faces": { + "north": {"uv": [2, 0, 14, 6], "texture": "#1"}, + "south": {"uv": [9, 0, 15, 4], "texture": "#0"}, + "up": {"uv": [10, 1, 14, 2], "rotation": 180, "texture": "#3"} + } + }, + { + "from": [0, 6, 6], + "to": [2, 14, 16], + "rotation": {"angle": 0, "axis": "y", "origin": [16, 0, 0]}, + "faces": { + "north": {"uv": [10, 9, 14, 8], "rotation": 90, "texture": "#3"}, + "east": {"uv": [10, 0, 0, 6], "texture": "#1"}, + "south": {"uv": [9, 0, 8, 4], "texture": "#0"}, + "west": {"uv": [16, 0, 7, 8], "texture": "#particle"}, + "up": {"uv": [9, 9, 14, 8], "rotation": 270, "texture": "#3"}, + "down": {"uv": [10, 9, 15, 8], "rotation": 270, "texture": "#3"} + } + }, + { + "from": [2, 6, 7], + "to": [14, 13, 14], + "faces": { + "north": {"uv": [0, 8, 3.5, 14], "rotation": 270, "texture": "#2"}, + "up": {"uv": [2.5, 8, 6, 14], "rotation": 90, "texture": "#2"}, + "down": {"uv": [2.5, 8, 6, 14], "rotation": 90, "texture": "#2"} + } + }, + { + "from": [0, 0, 8], + "to": [8, 6, 16], + "faces": { + "north": {"uv": [2, 5, 6, 8], "texture": "#6"}, + "east": {"uv": [0, 0, 0, 0], "texture": "#6"}, + "south": {"uv": [2, 5, 6, 8], "texture": "#6"}, + "west": {"uv": [2, 5, 6, 8], "texture": "#6"}, + "up": {"uv": [0, 0, 0, 0], "texture": "#6"}, + "down": {"uv": [0, 8, 4, 11], "texture": "#6"} + } + }, + { + "from": [8, 0, 8], + "to": [16, 6, 16], + "faces": { + "north": {"uv": [2, 5, 6, 8], "texture": "#6"}, + "east": {"uv": [2, 5, 6, 8], "texture": "#6"}, + "south": {"uv": [2, 5, 6, 8], "texture": "#6"}, + "west": {"uv": [0, 0, 0, 0], "texture": "#6"}, + "up": {"uv": [0, 0, 0, 0], "texture": "#6"}, + "down": {"uv": [4, 8, 8, 11], "texture": "#6"} + } + }, + { + "from": [0, 0, 4], + "to": [16, 4, 8], + "faces": { + "north": {"uv": [12, 0, 16, 16], "rotation": 90, "texture": "#1_5"}, + "east": {"uv": [12, 0, 16, 4], "rotation": 90, "texture": "#1_5"}, + "south": {"uv": [0, 0, 0, 0], "rotation": 90, "texture": "#6"}, + "west": {"uv": [12, 12, 16, 16], "rotation": 90, "texture": "#1_5"}, + "up": {"uv": [8, 0, 16, 2], "texture": "#6"}, + "down": {"uv": [6, 8, 8, 16], "rotation": 90, "texture": "#6"} + } + }, + { + "from": [6, 6.25, 6.75], + "to": [10, 13.25, 14.75], + "faces": { + "north": {"uv": [8.5, 1, 12, 3], "rotation": 270, "texture": "#7"}, + "up": {"uv": [8.5, 1, 12.5, 3], "rotation": 270, "texture": "#7"} + } + }, + { + "from": [0, 6.25, 6.75], + "to": [4, 13.25, 14.75], + "faces": { + "north": {"uv": [12, 1, 15.5, 3], "rotation": 90, "texture": "#7"}, + "up": {"uv": [11.5, 1, 15.5, 3], "rotation": 90, "texture": "#7"} + } + }, + { + "from": [12, 6.25, 6.75], + "to": [16, 13.25, 14.75], + "faces": { + "north": {"uv": [12, 1, 15.5, 3], "rotation": 90, "texture": "#7"}, + "up": {"uv": [11.5, 1, 15.5, 3], "rotation": 90, "texture": "#7"} + } } ], "display": { @@ -148,28 +178,38 @@ }, "groups": [ { - "name": "open", - "origin": [0, 0, 0], + "name": "lever", + "origin": [8, 8, 8], "color": 0, - "children": [0, 1, 2, 3, 4] + "children": [0] + }, + { + "name": "lever", + "origin": [8, 8, 8], + "color": 0, + "children": [1] + }, + { + "name": "block_open", + "origin": [8, 8, 8], + "color": 0, + "children": [ + { + "name": "open", + "origin": [0, 0, 0], + "color": 0, + "children": [2, 3, 4, 5] + }, + 6, + 7, + 8 + ] }, { "name": "cover", "origin": [8, 8, 8], "color": 0, - "children": [5, 6, 7] - }, - { - "name": "lever", - "origin": [8, 8, 8], - "color": 0, - "children": [8] - }, - { - "name": "lever", - "origin": [8, 8, 8], - "color": 0, - "children": [9] + "children": [9, 10, 11] } ] } \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/controls/train/cover.json b/src/main/resources/assets/create/models/block/controls/train/cover.json index 881c212d5..d75d6842b 100644 --- a/src/main/resources/assets/create/models/block/controls/train/cover.json +++ b/src/main/resources/assets/create/models/block/controls/train/cover.json @@ -6,27 +6,27 @@ }, "elements": [ { - "from": [6, 7.25, 6.75], + "from": [6, 6.25, 6.75], "to": [10, 13.25, 14.75], "faces": { - "north": {"uv": [10.5, 6, 13.5, 8], "rotation": 270, "texture": "#7"}, - "up": {"uv": [10, 6, 14, 8], "rotation": 90, "texture": "#7"} + "north": {"uv": [8.5, 1, 12, 3], "rotation": 270, "texture": "#7"}, + "up": {"uv": [8.5, 1, 12.5, 3], "rotation": 270, "texture": "#7"} } }, { - "from": [0, 7.25, 6.75], + "from": [0, 6.25, 6.75], "to": [4, 13.25, 14.75], "faces": { - "north": {"uv": [10.5, 6, 13.5, 8], "rotation": 270, "texture": "#7"}, - "up": {"uv": [10, 6, 14, 8], "rotation": 90, "texture": "#7"} + "north": {"uv": [12, 1, 15.5, 3], "rotation": 90, "texture": "#7"}, + "up": {"uv": [11.5, 1, 15.5, 3], "rotation": 90, "texture": "#7"} } }, { - "from": [12, 7.25, 6.75], + "from": [12, 6.25, 6.75], "to": [16, 13.25, 14.75], "faces": { - "north": {"uv": [10.5, 6, 13.5, 8], "rotation": 270, "texture": "#7"}, - "up": {"uv": [10, 6, 14, 8], "rotation": 90, "texture": "#7"} + "north": {"uv": [12, 1, 15.5, 3], "rotation": 90, "texture": "#7"}, + "up": {"uv": [11.5, 1, 15.5, 3], "rotation": 90, "texture": "#7"} } } ]