From 09691b4b40fc339a4e3dedec83358472e3e01725 Mon Sep 17 00:00:00 2001 From: simibubi <31564874+simibubi@users.noreply.github.com> Date: Wed, 26 May 2021 22:03:06 +0200 Subject: [PATCH] Redstone gamepads - Added the Linked Controller --- src/generated/resources/.cache/cache | 33 +-- .../resources/assets/create/lang/en_ud.json | 1 + .../resources/assets/create/lang/en_us.json | 7 + .../assets/create/lang/unfinished/de_de.json | 9 +- .../assets/create/lang/unfinished/es_es.json | 9 +- .../assets/create/lang/unfinished/es_mx.json | 9 +- .../assets/create/lang/unfinished/fr_fr.json | 9 +- .../assets/create/lang/unfinished/it_it.json | 9 +- .../assets/create/lang/unfinished/ja_jp.json | 9 +- .../assets/create/lang/unfinished/ko_kr.json | 9 +- .../assets/create/lang/unfinished/nl_nl.json | 9 +- .../assets/create/lang/unfinished/pl_pl.json | 9 +- .../assets/create/lang/unfinished/pt_br.json | 9 +- .../assets/create/lang/unfinished/ru_ru.json | 9 +- .../assets/create/lang/unfinished/zh_cn.json | 9 +- .../assets/create/lang/unfinished/zh_tw.json | 9 +- .../create/models/item/linked_controller.json | 3 + .../data/create/advancements/aesthetics.json | 4 +- .../simibubi/create/AllContainerTypes.java | 5 + .../java/com/simibubi/create/AllItems.java | 8 + .../goggles/GoggleOverlayRenderer.java | 4 +- .../content/logistics/IRedstoneLinkable.java | 23 ++ .../logistics/RedstoneLinkNetworkHandler.java | 66 +++-- .../item/LinkedControllerBindPacket.java | 55 +++++ .../item/LinkedControllerClientHandler.java | 225 ++++++++++++++++++ .../item/LinkedControllerContainer.java | 152 ++++++++++++ .../item/LinkedControllerInputPacket.java | 50 ++++ .../logistics/item/LinkedControllerItem.java | 116 +++++++++ .../item/LinkedControllerItemRenderer.java | 134 +++++++++++ .../logistics/item/LinkedControllerModel.java | 20 ++ .../item/LinkedControllerPacketBase.java | 37 +++ .../item/LinkedControllerScreen.java | 134 +++++++++++ .../item/LinkedControllerServerHandler.java | 123 ++++++++++ .../item/filter/AbstractFilterContainer.java | 7 +- .../item/filter/AbstractFilterScreen.java | 4 +- .../item/filter/AttributeFilterContainer.java | 2 +- .../item/filter/FilterScreenPacket.java | 10 +- .../simibubi/create/events/ClientEvents.java | 4 + .../simibubi/create/events/CommonEvents.java | 2 + .../create/foundation/gui/AllGuiTextures.java | 2 + .../foundation/gui/ClearContainerPacket.java | 36 +++ .../foundation/gui/IClearableContainer.java | 13 + .../foundation/networking/AllPackets.java | 8 +- .../foundation/renderState/RenderTypes.java | 2 +- .../tileEntity/TileEntityBehaviour.java | 1 - .../behaviour/linked/LinkBehaviour.java | 38 ++- .../behaviour/linked/LinkHandler.java | 11 +- .../assets/create/lang/default/messages.json | 6 + .../models/item/linked_controller/button.json | 22 ++ .../models/item/linked_controller/item.json | 166 +++++++++++++ .../item/linked_controller/powered.json | 94 ++++++++ .../create/textures/gui/curiosities2.png | Bin 0 -> 1407 bytes .../textures/item/linked_controller.png | Bin 0 -> 351 bytes .../item/linked_controller_powered.png | Bin 0 -> 350 bytes .../create/textures/item/refined_radiance.png | Bin 242 -> 262 bytes 55 files changed, 1649 insertions(+), 96 deletions(-) create mode 100644 src/generated/resources/assets/create/models/item/linked_controller.json create mode 100644 src/main/java/com/simibubi/create/content/logistics/IRedstoneLinkable.java create mode 100644 src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerBindPacket.java create mode 100644 src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerClientHandler.java create mode 100644 src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerContainer.java create mode 100644 src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerInputPacket.java create mode 100644 src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerItem.java create mode 100644 src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerItemRenderer.java create mode 100644 src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerModel.java create mode 100644 src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerPacketBase.java create mode 100644 src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerScreen.java create mode 100644 src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerServerHandler.java create mode 100644 src/main/java/com/simibubi/create/foundation/gui/ClearContainerPacket.java create mode 100644 src/main/java/com/simibubi/create/foundation/gui/IClearableContainer.java create mode 100644 src/main/resources/assets/create/models/item/linked_controller/button.json create mode 100644 src/main/resources/assets/create/models/item/linked_controller/item.json create mode 100644 src/main/resources/assets/create/models/item/linked_controller/powered.json create mode 100644 src/main/resources/assets/create/textures/gui/curiosities2.png create mode 100644 src/main/resources/assets/create/textures/item/linked_controller.png create mode 100644 src/main/resources/assets/create/textures/item/linked_controller_powered.png diff --git a/src/generated/resources/.cache/cache b/src/generated/resources/.cache/cache index fb6f24a64..091f2d332 100644 --- a/src/generated/resources/.cache/cache +++ b/src/generated/resources/.cache/cache @@ -407,21 +407,21 @@ a3a11524cd3515fc01d905767b4b7ea782adaf03 assets/create/blockstates/yellow_seat.j 6801fa1f466f172700e573e5b8ee8ee5f9ca4583 assets/create/blockstates/yellow_valve_handle.json 7f39521b211441f5c3e06d60c5978cebe16cacfb assets/create/blockstates/zinc_block.json b7181bcd8182b2f17088e5aa881f374c9c65470c assets/create/blockstates/zinc_ore.json -a6d814f94926d88764c38862cc4ece9c367e023b assets/create/lang/en_ud.json -d1838140c8383ee4537db90eb8f657d0c268fe91 assets/create/lang/en_us.json -4fcda300efe5a2ad8695b5ae3f24a54ea109a954 assets/create/lang/unfinished/de_de.json -6a1dde57b2224d4b0287ebc705d6a75d329b5e1f assets/create/lang/unfinished/es_es.json -93ee0e30a56b405a9e766d353c36276e36a84b5c assets/create/lang/unfinished/es_mx.json -49a691320c73e09f921cd0ea97398126231e99fa assets/create/lang/unfinished/fr_fr.json -cf14b3828b6c11013f606f277d88fb63245bb2a8 assets/create/lang/unfinished/it_it.json -73c1c1489833cbcb28bb1ce90541c8c8bdf329c0 assets/create/lang/unfinished/ja_jp.json -924303b9bcf56aedbbfc46108655f71324308e12 assets/create/lang/unfinished/ko_kr.json -079aea6843e756efbfca0976983be1957863717c assets/create/lang/unfinished/nl_nl.json -b7bab15167400ee48a9728f81446e572c494fd8d assets/create/lang/unfinished/pl_pl.json -07e84cc3eee3faa1ab3d26e0c85c7f09c8573368 assets/create/lang/unfinished/pt_br.json -6ffb0cf20d712aee23a42a9ec440dd7dc92293d6 assets/create/lang/unfinished/ru_ru.json -0ae98a18e59f478da41d8c5d832737b65f6a8c8a assets/create/lang/unfinished/zh_cn.json -4c96e5a76e72368a59190b7588d389fdd2cc75e1 assets/create/lang/unfinished/zh_tw.json +e9c463e0cf56ed28ee26a33debeae3ecc2e941d2 assets/create/lang/en_ud.json +a9a31be19fc2e109967e68b63746dee766b8b4d1 assets/create/lang/en_us.json +916eb5e579f283b81f100098bf168203d75db5c5 assets/create/lang/unfinished/de_de.json +fc1a5dc58cb00012cd311f909de3cd6085664994 assets/create/lang/unfinished/es_es.json +7716f8e2a1cc161778e627f6c1f527356cfd34f9 assets/create/lang/unfinished/es_mx.json +2e032434706937780312c8c9a72ec0e0a8f1a8e6 assets/create/lang/unfinished/fr_fr.json +011b39c4217c2d5da59d0c8f4fd3c5f272a91c3e assets/create/lang/unfinished/it_it.json +dd04db4e469ece034e9edde1d182d40ece3c917f assets/create/lang/unfinished/ja_jp.json +a46af574991af844c58a7fe75b4c2b0ac888b4e0 assets/create/lang/unfinished/ko_kr.json +1ee72b0c9ac509ffcd17b19d17ab1f4b3506c9ce assets/create/lang/unfinished/nl_nl.json +b23f249ef0b28b2e2312e63f2fccf4401b282ac4 assets/create/lang/unfinished/pl_pl.json +73030bf3d5aace5c3e991c6bf265322bba42286f assets/create/lang/unfinished/pt_br.json +73b1927e1d32e4229caa96e8d1bc25d39fb51377 assets/create/lang/unfinished/ru_ru.json +aa3f0b918d948795e10878c3d42dbd4c39f71795 assets/create/lang/unfinished/zh_cn.json +1f15238d524e7b94b0ce5bcd09703b4742b9f960 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 @@ -1452,6 +1452,7 @@ ebdf23b99b7895e347c29057c8070a6e16e56beb assets/create/models/item/limestone_cob 288da8b29a4e9d0d0b694567a61b5a816a2859b8 assets/create/models/item/limestone_cobblestone_wall.json 8065de871ad2fbaed711735561b8ed91a2ce0004 assets/create/models/item/limestone_pillar.json d245aa4994ff197b1ffeb7980d05f96bd20cdeb3 assets/create/models/item/linear_chassis.json +2866bff509b060cd3ee99b4eef25a4e1e4639703 assets/create/models/item/linked_controller.json d912be3e87f2beaa8e22747f867739139667241b assets/create/models/item/magenta_seat.json 928c5e3747fb758d2610475258cc168b0d4ee7b6 assets/create/models/item/magenta_valve_handle.json 932facf4bf93b471e8630f4132a4284a9f4d0d39 assets/create/models/item/mechanical_arm.json @@ -1652,7 +1653,7 @@ d080b1b25e5bc8baf5aee68691b08c7f12ece3b0 assets/create/models/item/windmill_bear a80fb25a0b655e76be986b5b49fcb0f03461a1ab assets/create/models/item/zinc_nugget.json b1689617190c05ef34bd18456b0c7ae09bb3210f assets/create/models/item/zinc_ore.json 096382a4c025b5ffdde9c496ee9da0d5345fbe17 assets/create/sounds.json -5d0cc4c0255dc241e61c173b31ddca70c88d08e4 data/create/advancements/aesthetics.json +0f1b4b980afba9bf2caf583b88e261bba8b10313 data/create/advancements/aesthetics.json 187921fa131b06721bfaf63f2623a28c141aae9a data/create/advancements/andesite_alloy.json 0ea2db7173b5be28b289ea7c9a6a0cf5805c60c7 data/create/advancements/andesite_casing.json 83c046bd200623933545c9e4326f782fb02c87fa data/create/advancements/arm_blaze_burner.json diff --git a/src/generated/resources/assets/create/lang/en_ud.json b/src/generated/resources/assets/create/lang/en_ud.json index 12c9bc03a..80d533b06 100644 --- a/src/generated/resources/assets/create/lang/en_ud.json +++ b/src/generated/resources/assets/create/lang/en_ud.json @@ -468,6 +468,7 @@ "item.create.integrated_circuit": "\u0287\u0131n\u0254\u0279\u0131\u0186 p\u01DD\u0287\u0250\u0279b\u01DD\u0287uI", "item.create.iron_sheet": "\u0287\u01DD\u01DD\u0265S uo\u0279I", "item.create.lapis_sheet": "\u0287\u01DD\u01DD\u0265S s\u0131d\u0250\uA780", + "item.create.linked_controller": "\u0279\u01DD\u05DF\u05DFo\u0279\u0287uo\u0186 p\u01DD\u029Eu\u0131\uA780", "item.create.minecart_contraption": "uo\u0131\u0287d\u0250\u0279\u0287uo\u0186 \u0287\u0279\u0250\u0254\u01DDu\u0131W", "item.create.minecart_coupling": "bu\u0131\u05DFdno\u0186 \u0287\u0279\u0250\u0254\u01DDu\u0131W", "item.create.polished_rose_quartz": "z\u0287\u0279\u0250n\u1F49 \u01DDso\u1D1A p\u01DD\u0265s\u0131\u05DFo\u0500", diff --git a/src/generated/resources/assets/create/lang/en_us.json b/src/generated/resources/assets/create/lang/en_us.json index 427d2c658..5386c44f9 100644 --- a/src/generated/resources/assets/create/lang/en_us.json +++ b/src/generated/resources/assets/create/lang/en_us.json @@ -474,6 +474,7 @@ "item.create.integrated_circuit": "Integrated Circuit", "item.create.iron_sheet": "Iron Sheet", "item.create.lapis_sheet": "Lapis Sheet", + "item.create.linked_controller": "Linked Controller", "item.create.minecart_contraption": "Minecart Contraption", "item.create.minecart_coupling": "Minecart Coupling", "item.create.polished_rose_quartz": "Polished Rose Quartz", @@ -1104,6 +1105,12 @@ "create.tooltip.chute.fans_pull_down": "Fans pull from Below", "create.tooltip.chute.contains": "Contains: %1$s x%2$s", + "create.linked_controller.bind_mode": "Bind mode active", + "create.linked_controller.press_keybind": "Press %1$s, %2$s, %3$s, %4$s, %5$s or %6$s, to bind this frequency to the respective key", + "create.linked_controller.key_bound": "Frequency bound to %1$s", + "create.linked_controller.frequency_slot_1": "Keybind: %1$s, Freq. #1", + "create.linked_controller.frequency_slot_2": "Keybind: %1$s, Freq. #2", + "create.hint.hose_pulley.title": "Bottomless Supply", "create.hint.hose_pulley": "The targeted body of fluid is considered infinite.", "create.hint.mechanical_arm_no_targets.title": "No Targets", 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 bffa0a121..35b456937 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: 942", + "_": "Missing Localizations: 948", "_": "->------------------------] Game Elements [------------------------<-", @@ -475,6 +475,7 @@ "item.create.integrated_circuit": "Integrierter Schaltkreis", "item.create.iron_sheet": "Eisenblech", "item.create.lapis_sheet": "Lapislazuliblech", + "item.create.linked_controller": "UNLOCALIZED: Linked Controller", "item.create.minecart_contraption": "Loren Vorrichtung", "item.create.minecart_coupling": "Lorenkupplung", "item.create.polished_rose_quartz": "Polierter Rosenquarz", @@ -1105,6 +1106,12 @@ "create.tooltip.chute.fans_pull_down": "Propeller ziehen von unterhalb", "create.tooltip.chute.contains": "Enthält: %1$s x%2$s", + "create.linked_controller.bind_mode": "UNLOCALIZED: Bind mode active", + "create.linked_controller.press_keybind": "UNLOCALIZED: Press %1$s, %2$s, %3$s, %4$s, %5$s or %6$s, to bind this frequency to the respective key", + "create.linked_controller.key_bound": "UNLOCALIZED: Frequency bound to %1$s", + "create.linked_controller.frequency_slot_1": "UNLOCALIZED: Keybind: %1$s, Freq. #1", + "create.linked_controller.frequency_slot_2": "UNLOCALIZED: Keybind: %1$s, Freq. #2", + "create.hint.hose_pulley.title": "Endlose Versorgung", "create.hint.hose_pulley": "Das angewählte Gewässer wird als unendlich betrachtet.", "create.hint.mechanical_arm_no_targets.title": "Keine Ziele", 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 12880cfef..0d801148c 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: 643", + "_": "Missing Localizations: 649", "_": "->------------------------] Game Elements [------------------------<-", @@ -475,6 +475,7 @@ "item.create.integrated_circuit": "Chip de circuito integrado", "item.create.iron_sheet": "Lámina de hierro", "item.create.lapis_sheet": "Lámina de lapislázuli", + "item.create.linked_controller": "UNLOCALIZED: Linked Controller", "item.create.minecart_contraption": "Artilugio de vagoneta", "item.create.minecart_coupling": "Acoplamiento de vagoneta", "item.create.polished_rose_quartz": "Cuarzo rosado pulido", @@ -1105,6 +1106,12 @@ "create.tooltip.chute.fans_pull_down": "Los ventiladores tiran desde abajo", "create.tooltip.chute.contains": "Contiene: %1$s x%2$s", + "create.linked_controller.bind_mode": "UNLOCALIZED: Bind mode active", + "create.linked_controller.press_keybind": "UNLOCALIZED: Press %1$s, %2$s, %3$s, %4$s, %5$s or %6$s, to bind this frequency to the respective key", + "create.linked_controller.key_bound": "UNLOCALIZED: Frequency bound to %1$s", + "create.linked_controller.frequency_slot_1": "UNLOCALIZED: Keybind: %1$s, Freq. #1", + "create.linked_controller.frequency_slot_2": "UNLOCALIZED: Keybind: %1$s, Freq. #2", + "create.hint.hose_pulley.title": "Suministro sin fondo", "create.hint.hose_pulley": "La masa de fluido objetivo se considera infinita", "create.hint.mechanical_arm_no_targets.title": "No hay objetivos", diff --git a/src/generated/resources/assets/create/lang/unfinished/es_mx.json b/src/generated/resources/assets/create/lang/unfinished/es_mx.json index f3de8dd15..6919bdae1 100644 --- a/src/generated/resources/assets/create/lang/unfinished/es_mx.json +++ b/src/generated/resources/assets/create/lang/unfinished/es_mx.json @@ -1,5 +1,5 @@ { - "_": "Missing Localizations: 1266", + "_": "Missing Localizations: 1272", "_": "->------------------------] Game Elements [------------------------<-", @@ -475,6 +475,7 @@ "item.create.integrated_circuit": "Circuito Integrado", "item.create.iron_sheet": "Lámina de Hierro", "item.create.lapis_sheet": "Lámina de Lapislázuli", + "item.create.linked_controller": "UNLOCALIZED: Linked Controller", "item.create.minecart_contraption": "Artefacto de Vagón", "item.create.minecart_coupling": "Acoplamiento de Vagonetas", "item.create.polished_rose_quartz": "Cuarzo Rosa Pulido", @@ -1105,6 +1106,12 @@ "create.tooltip.chute.fans_pull_down": "UNLOCALIZED: Fans pull from Below", "create.tooltip.chute.contains": "UNLOCALIZED: Contains: %1$s x%2$s", + "create.linked_controller.bind_mode": "UNLOCALIZED: Bind mode active", + "create.linked_controller.press_keybind": "UNLOCALIZED: Press %1$s, %2$s, %3$s, %4$s, %5$s or %6$s, to bind this frequency to the respective key", + "create.linked_controller.key_bound": "UNLOCALIZED: Frequency bound to %1$s", + "create.linked_controller.frequency_slot_1": "UNLOCALIZED: Keybind: %1$s, Freq. #1", + "create.linked_controller.frequency_slot_2": "UNLOCALIZED: Keybind: %1$s, Freq. #2", + "create.hint.hose_pulley.title": "UNLOCALIZED: Bottomless Supply", "create.hint.hose_pulley": "UNLOCALIZED: The targeted body of fluid is considered infinite.", "create.hint.mechanical_arm_no_targets.title": "UNLOCALIZED: No Targets", 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 558c2ff87..f6b6cc6a8 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: 1194", + "_": "Missing Localizations: 1200", "_": "->------------------------] Game Elements [------------------------<-", @@ -475,6 +475,7 @@ "item.create.integrated_circuit": "Circuit intégré", "item.create.iron_sheet": "Plaque de Fer", "item.create.lapis_sheet": "Feuille de lapis", + "item.create.linked_controller": "UNLOCALIZED: Linked Controller", "item.create.minecart_contraption": "Engin de wagonnet", "item.create.minecart_coupling": "Lien pour wagonnet", "item.create.polished_rose_quartz": "Quartz rose poli", @@ -1105,6 +1106,12 @@ "create.tooltip.chute.fans_pull_down": "UNLOCALIZED: Fans pull from Below", "create.tooltip.chute.contains": "UNLOCALIZED: Contains: %1$s x%2$s", + "create.linked_controller.bind_mode": "UNLOCALIZED: Bind mode active", + "create.linked_controller.press_keybind": "UNLOCALIZED: Press %1$s, %2$s, %3$s, %4$s, %5$s or %6$s, to bind this frequency to the respective key", + "create.linked_controller.key_bound": "UNLOCALIZED: Frequency bound to %1$s", + "create.linked_controller.frequency_slot_1": "UNLOCALIZED: Keybind: %1$s, Freq. #1", + "create.linked_controller.frequency_slot_2": "UNLOCALIZED: Keybind: %1$s, Freq. #2", + "create.hint.hose_pulley.title": "UNLOCALIZED: Bottomless Supply", "create.hint.hose_pulley": "UNLOCALIZED: The targeted body of fluid is considered infinite.", "create.hint.mechanical_arm_no_targets.title": "UNLOCALIZED: No Targets", 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 afa0b3942..687d7ca8b 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: 660", + "_": "Missing Localizations: 666", "_": "->------------------------] Game Elements [------------------------<-", @@ -475,6 +475,7 @@ "item.create.integrated_circuit": "Circuito integrato", "item.create.iron_sheet": "Lamiera di ferro", "item.create.lapis_sheet": "Lamiera di lapislazzuli", + "item.create.linked_controller": "UNLOCALIZED: Linked Controller", "item.create.minecart_contraption": "Contrazione per carrello da miniera", "item.create.minecart_coupling": "Aggancio per carrelli da miniera", "item.create.polished_rose_quartz": "Quarzo rosa levigato", @@ -1105,6 +1106,12 @@ "create.tooltip.chute.fans_pull_down": "I ventilatori tirano da sotto", "create.tooltip.chute.contains": "Contiene: %1$s x%2$s", + "create.linked_controller.bind_mode": "UNLOCALIZED: Bind mode active", + "create.linked_controller.press_keybind": "UNLOCALIZED: Press %1$s, %2$s, %3$s, %4$s, %5$s or %6$s, to bind this frequency to the respective key", + "create.linked_controller.key_bound": "UNLOCALIZED: Frequency bound to %1$s", + "create.linked_controller.frequency_slot_1": "UNLOCALIZED: Keybind: %1$s, Freq. #1", + "create.linked_controller.frequency_slot_2": "UNLOCALIZED: Keybind: %1$s, Freq. #2", + "create.hint.hose_pulley.title": "Buco senza fondo", "create.hint.hose_pulley": "Il corpo fluido selezionato è considerato infinito.", "create.hint.mechanical_arm_no_targets.title": "Nessun bersaglio", 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 9bf53aabf..57dc32780 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: 24", + "_": "Missing Localizations: 30", "_": "->------------------------] Game Elements [------------------------<-", @@ -475,6 +475,7 @@ "item.create.integrated_circuit": "集積回路", "item.create.iron_sheet": "鉄板", "item.create.lapis_sheet": "ラピスラズリ板", + "item.create.linked_controller": "UNLOCALIZED: Linked Controller", "item.create.minecart_contraption": "からくり付きトロッコ", "item.create.minecart_coupling": "トロッコ連結器", "item.create.polished_rose_quartz": "磨かれたローズクォーツ", @@ -1105,6 +1106,12 @@ "create.tooltip.chute.fans_pull_down": "ファンが下から吸い込んでいます", "create.tooltip.chute.contains": "内容物: %1$s x%2$s", + "create.linked_controller.bind_mode": "UNLOCALIZED: Bind mode active", + "create.linked_controller.press_keybind": "UNLOCALIZED: Press %1$s, %2$s, %3$s, %4$s, %5$s or %6$s, to bind this frequency to the respective key", + "create.linked_controller.key_bound": "UNLOCALIZED: Frequency bound to %1$s", + "create.linked_controller.frequency_slot_1": "UNLOCALIZED: Keybind: %1$s, Freq. #1", + "create.linked_controller.frequency_slot_2": "UNLOCALIZED: Keybind: %1$s, Freq. #2", + "create.hint.hose_pulley.title": "底なし搬出", "create.hint.hose_pulley": "対象となる液体は無限とみなされています。", "create.hint.mechanical_arm_no_targets.title": "ターゲットが見つかりません", 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 17289ec89..2b0032b45 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: 713", + "_": "Missing Localizations: 719", "_": "->------------------------] Game Elements [------------------------<-", @@ -475,6 +475,7 @@ "item.create.integrated_circuit": "집적 회로", "item.create.iron_sheet": "철 판", "item.create.lapis_sheet": "청금석 판", + "item.create.linked_controller": "UNLOCALIZED: Linked Controller", "item.create.minecart_contraption": "광산 수레 장치", "item.create.minecart_coupling": "광산 수레 커플링", "item.create.polished_rose_quartz": "윤나는 장밋빛 석영", @@ -1105,6 +1106,12 @@ "create.tooltip.chute.fans_pull_down": "선풍기가 아래에서 당김", "create.tooltip.chute.contains": "UNLOCALIZED: Contains: %1$s x%2$s", + "create.linked_controller.bind_mode": "UNLOCALIZED: Bind mode active", + "create.linked_controller.press_keybind": "UNLOCALIZED: Press %1$s, %2$s, %3$s, %4$s, %5$s or %6$s, to bind this frequency to the respective key", + "create.linked_controller.key_bound": "UNLOCALIZED: Frequency bound to %1$s", + "create.linked_controller.frequency_slot_1": "UNLOCALIZED: Keybind: %1$s, Freq. #1", + "create.linked_controller.frequency_slot_2": "UNLOCALIZED: Keybind: %1$s, Freq. #2", + "create.hint.hose_pulley.title": "UNLOCALIZED: Bottomless Supply", "create.hint.hose_pulley": "UNLOCALIZED: The targeted body of fluid is considered infinite.", "create.hint.mechanical_arm_no_targets.title": "목표 없음", 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 acb783a8e..a6cd4e26d 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: 1577", + "_": "Missing Localizations: 1583", "_": "->------------------------] Game Elements [------------------------<-", @@ -475,6 +475,7 @@ "item.create.integrated_circuit": "UNLOCALIZED: Integrated Circuit", "item.create.iron_sheet": "IJzeren Platen", "item.create.lapis_sheet": "UNLOCALIZED: Lapis Sheet", + "item.create.linked_controller": "UNLOCALIZED: Linked Controller", "item.create.minecart_contraption": "UNLOCALIZED: Minecart Contraption", "item.create.minecart_coupling": "UNLOCALIZED: Minecart Coupling", "item.create.polished_rose_quartz": "UNLOCALIZED: Polished Rose Quartz", @@ -1105,6 +1106,12 @@ "create.tooltip.chute.fans_pull_down": "UNLOCALIZED: Fans pull from Below", "create.tooltip.chute.contains": "UNLOCALIZED: Contains: %1$s x%2$s", + "create.linked_controller.bind_mode": "UNLOCALIZED: Bind mode active", + "create.linked_controller.press_keybind": "UNLOCALIZED: Press %1$s, %2$s, %3$s, %4$s, %5$s or %6$s, to bind this frequency to the respective key", + "create.linked_controller.key_bound": "UNLOCALIZED: Frequency bound to %1$s", + "create.linked_controller.frequency_slot_1": "UNLOCALIZED: Keybind: %1$s, Freq. #1", + "create.linked_controller.frequency_slot_2": "UNLOCALIZED: Keybind: %1$s, Freq. #2", + "create.hint.hose_pulley.title": "UNLOCALIZED: Bottomless Supply", "create.hint.hose_pulley": "UNLOCALIZED: The targeted body of fluid is considered infinite.", "create.hint.mechanical_arm_no_targets.title": "UNLOCALIZED: No Targets", 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 3b4dd77cd..e52917f1b 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: 38", + "_": "Missing Localizations: 44", "_": "->------------------------] Game Elements [------------------------<-", @@ -475,6 +475,7 @@ "item.create.integrated_circuit": "Układ scalony", "item.create.iron_sheet": "Arkusz żelaza", "item.create.lapis_sheet": "Arkusz lazurytu", + "item.create.linked_controller": "UNLOCALIZED: Linked Controller", "item.create.minecart_contraption": "Maszyna w wagoniku", "item.create.minecart_coupling": "Łącznik wagoników", "item.create.polished_rose_quartz": "Wypolerowany kwarc różowy", @@ -1105,6 +1106,12 @@ "create.tooltip.chute.fans_pull_down": "Wiatraki ciągną od dołu", "create.tooltip.chute.contains": "Zawiera: %1$s x%2$s", + "create.linked_controller.bind_mode": "UNLOCALIZED: Bind mode active", + "create.linked_controller.press_keybind": "UNLOCALIZED: Press %1$s, %2$s, %3$s, %4$s, %5$s or %6$s, to bind this frequency to the respective key", + "create.linked_controller.key_bound": "UNLOCALIZED: Frequency bound to %1$s", + "create.linked_controller.frequency_slot_1": "UNLOCALIZED: Keybind: %1$s, Freq. #1", + "create.linked_controller.frequency_slot_2": "UNLOCALIZED: Keybind: %1$s, Freq. #2", + "create.hint.hose_pulley.title": "Niewyczerpany zapas", "create.hint.hose_pulley": "Wybrane zbiornik cieczy jest uznany za nieskończony", "create.hint.mechanical_arm_no_targets.title": "Brak celi", 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 4d81d99bb..dc42dec85 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: 1629", + "_": "Missing Localizations: 1635", "_": "->------------------------] Game Elements [------------------------<-", @@ -475,6 +475,7 @@ "item.create.integrated_circuit": "UNLOCALIZED: Integrated Circuit", "item.create.iron_sheet": "Placas de Ferro", "item.create.lapis_sheet": "UNLOCALIZED: Lapis Sheet", + "item.create.linked_controller": "UNLOCALIZED: Linked Controller", "item.create.minecart_contraption": "UNLOCALIZED: Minecart Contraption", "item.create.minecart_coupling": "UNLOCALIZED: Minecart Coupling", "item.create.polished_rose_quartz": "UNLOCALIZED: Polished Rose Quartz", @@ -1105,6 +1106,12 @@ "create.tooltip.chute.fans_pull_down": "UNLOCALIZED: Fans pull from Below", "create.tooltip.chute.contains": "UNLOCALIZED: Contains: %1$s x%2$s", + "create.linked_controller.bind_mode": "UNLOCALIZED: Bind mode active", + "create.linked_controller.press_keybind": "UNLOCALIZED: Press %1$s, %2$s, %3$s, %4$s, %5$s or %6$s, to bind this frequency to the respective key", + "create.linked_controller.key_bound": "UNLOCALIZED: Frequency bound to %1$s", + "create.linked_controller.frequency_slot_1": "UNLOCALIZED: Keybind: %1$s, Freq. #1", + "create.linked_controller.frequency_slot_2": "UNLOCALIZED: Keybind: %1$s, Freq. #2", + "create.hint.hose_pulley.title": "UNLOCALIZED: Bottomless Supply", "create.hint.hose_pulley": "UNLOCALIZED: The targeted body of fluid is considered infinite.", "create.hint.mechanical_arm_no_targets.title": "UNLOCALIZED: No Targets", 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 1f092d472..994185e4e 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: 557", + "_": "Missing Localizations: 563", "_": "->------------------------] Game Elements [------------------------<-", @@ -475,6 +475,7 @@ "item.create.integrated_circuit": "Интегральная схема", "item.create.iron_sheet": "Железный лист", "item.create.lapis_sheet": "Лазуритовый лист", + "item.create.linked_controller": "UNLOCALIZED: Linked Controller", "item.create.minecart_contraption": "Вагонеточная штуковина", "item.create.minecart_coupling": "Связыватель вагонеток", "item.create.polished_rose_quartz": "Полированный розовый кварц", @@ -1105,6 +1106,12 @@ "create.tooltip.chute.fans_pull_down": "Вентилятор тянет снизу", "create.tooltip.chute.contains": "Содержит: %1$s x%2$s", + "create.linked_controller.bind_mode": "UNLOCALIZED: Bind mode active", + "create.linked_controller.press_keybind": "UNLOCALIZED: Press %1$s, %2$s, %3$s, %4$s, %5$s or %6$s, to bind this frequency to the respective key", + "create.linked_controller.key_bound": "UNLOCALIZED: Frequency bound to %1$s", + "create.linked_controller.frequency_slot_1": "UNLOCALIZED: Keybind: %1$s, Freq. #1", + "create.linked_controller.frequency_slot_2": "UNLOCALIZED: Keybind: %1$s, Freq. #2", + "create.hint.hose_pulley.title": "Безграничное снабжение", "create.hint.hose_pulley": "Целевой водный резервуар считается бесконечным.", "create.hint.mechanical_arm_no_targets.title": "Нет целей", 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 513325f0d..2e733b1b0 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: 43", + "_": "Missing Localizations: 49", "_": "->------------------------] Game Elements [------------------------<-", @@ -475,6 +475,7 @@ "item.create.integrated_circuit": "集成电路板", "item.create.iron_sheet": "铁板", "item.create.lapis_sheet": "青金石板", + "item.create.linked_controller": "UNLOCALIZED: Linked Controller", "item.create.minecart_contraption": "装配过的矿车", "item.create.minecart_coupling": "矿车连轴器", "item.create.polished_rose_quartz": "磨制玫瑰石英", @@ -1105,6 +1106,12 @@ "create.tooltip.chute.fans_pull_down": "鼓风机从下方进行吸引", "create.tooltip.chute.contains": "内含物品:%1$s x%2$s", + "create.linked_controller.bind_mode": "UNLOCALIZED: Bind mode active", + "create.linked_controller.press_keybind": "UNLOCALIZED: Press %1$s, %2$s, %3$s, %4$s, %5$s or %6$s, to bind this frequency to the respective key", + "create.linked_controller.key_bound": "UNLOCALIZED: Frequency bound to %1$s", + "create.linked_controller.frequency_slot_1": "UNLOCALIZED: Keybind: %1$s, Freq. #1", + "create.linked_controller.frequency_slot_2": "UNLOCALIZED: Keybind: %1$s, Freq. #2", + "create.hint.hose_pulley.title": "无限供应", "create.hint.hose_pulley": "目标液体对象被视为无限量的。", "create.hint.mechanical_arm_no_targets.title": "没有目标", 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 8b3a4f40a..5514b4f70 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: 662", + "_": "Missing Localizations: 668", "_": "->------------------------] Game Elements [------------------------<-", @@ -475,6 +475,7 @@ "item.create.integrated_circuit": "IC板", "item.create.iron_sheet": "鐵板", "item.create.lapis_sheet": "青金石板", + "item.create.linked_controller": "UNLOCALIZED: Linked Controller", "item.create.minecart_contraption": "裝修過的礦車", "item.create.minecart_coupling": "礦車連結器", "item.create.polished_rose_quartz": "磨製玫瑰石英", @@ -1105,6 +1106,12 @@ "create.tooltip.chute.fans_pull_down": "鼓風機從上方進行吸引", "create.tooltip.chute.contains": "UNLOCALIZED: Contains: %1$s x%2$s", + "create.linked_controller.bind_mode": "UNLOCALIZED: Bind mode active", + "create.linked_controller.press_keybind": "UNLOCALIZED: Press %1$s, %2$s, %3$s, %4$s, %5$s or %6$s, to bind this frequency to the respective key", + "create.linked_controller.key_bound": "UNLOCALIZED: Frequency bound to %1$s", + "create.linked_controller.frequency_slot_1": "UNLOCALIZED: Keybind: %1$s, Freq. #1", + "create.linked_controller.frequency_slot_2": "UNLOCALIZED: Keybind: %1$s, Freq. #2", + "create.hint.hose_pulley.title": "UNLOCALIZED: Bottomless Supply", "create.hint.hose_pulley": "UNLOCALIZED: The targeted body of fluid is considered infinite.", "create.hint.mechanical_arm_no_targets.title": "沒有目標", diff --git a/src/generated/resources/assets/create/models/item/linked_controller.json b/src/generated/resources/assets/create/models/item/linked_controller.json new file mode 100644 index 000000000..6bf114f21 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/linked_controller.json @@ -0,0 +1,3 @@ +{ + "parent": "create:item/linked_controller/item" +} \ No newline at end of file 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/AllContainerTypes.java b/src/main/java/com/simibubi/create/AllContainerTypes.java index 2e5e87d8d..e171543a9 100644 --- a/src/main/java/com/simibubi/create/AllContainerTypes.java +++ b/src/main/java/com/simibubi/create/AllContainerTypes.java @@ -2,6 +2,8 @@ package com.simibubi.create; import com.simibubi.create.content.logistics.block.inventories.AdjustableCrateContainer; import com.simibubi.create.content.logistics.block.inventories.AdjustableCrateScreen; +import com.simibubi.create.content.logistics.item.LinkedControllerContainer; +import com.simibubi.create.content.logistics.item.LinkedControllerScreen; import com.simibubi.create.content.logistics.item.filter.AttributeFilterContainer; import com.simibubi.create.content.logistics.item.filter.AttributeFilterScreen; import com.simibubi.create.content.logistics.item.filter.FilterContainer; @@ -35,6 +37,9 @@ public class AllContainerTypes { public static final ContainerEntry ATTRIBUTE_FILTER = register("attribute_filter", AttributeFilterContainer::new, () -> AttributeFilterScreen::new); + + public static final ContainerEntry LINKED_CONTROLLER = + register("linked_controller", LinkedControllerContainer::new, () -> LinkedControllerScreen::new); private static > ContainerEntry register(String name, ForgeContainerFactory factory, NonNullSupplier> screenFactory) { return Create.registrate().container(name, factory, screenFactory).register(); diff --git a/src/main/java/com/simibubi/create/AllItems.java b/src/main/java/com/simibubi/create/AllItems.java index 901ab6710..25a418064 100644 --- a/src/main/java/com/simibubi/create/AllItems.java +++ b/src/main/java/com/simibubi/create/AllItems.java @@ -41,6 +41,8 @@ import com.simibubi.create.content.curiosities.tools.SandPaperItem; import com.simibubi.create.content.curiosities.tools.SandPaperItemRenderer.SandPaperModel; import com.simibubi.create.content.curiosities.zapper.terrainzapper.WorldshaperItem; import com.simibubi.create.content.curiosities.zapper.terrainzapper.WorldshaperModel; +import com.simibubi.create.content.logistics.item.LinkedControllerItem; +import com.simibubi.create.content.logistics.item.LinkedControllerModel; import com.simibubi.create.content.logistics.item.filter.FilterItem; import com.simibubi.create.content.schematics.item.SchematicAndQuillItem; import com.simibubi.create.content.schematics.item.SchematicItem; @@ -227,6 +229,12 @@ public class AllItems { .lang("Creative Worldshaper") .model(AssetLookup.itemModelWithPartials()) .register(); + + public static final ItemEntry LINKED_CONTROLLER = + REGISTRATE.item("linked_controller", LinkedControllerItem::new) + .transform(CreateRegistrate.customRenderedItem(() -> LinkedControllerModel::new)) + .model(AssetLookup.itemModelWithPartials()) + .register(); public static final ItemEntry MINECART_CONTRAPTION = REGISTRATE.item("minecart_contraption", MinecartContraptionItem::rideable) diff --git a/src/main/java/com/simibubi/create/content/contraptions/goggles/GoggleOverlayRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/goggles/GoggleOverlayRenderer.java index 1caccf3d5..3bd7cebd9 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/goggles/GoggleOverlayRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/goggles/GoggleOverlayRenderer.java @@ -172,8 +172,8 @@ public class GoggleOverlayRenderer { ms.pop(); } - private static final class TooltipScreen extends Screen { - private TooltipScreen(ITextComponent p_i51108_1_) { + public static final class TooltipScreen extends Screen { + public TooltipScreen(ITextComponent p_i51108_1_) { super(p_i51108_1_); } diff --git a/src/main/java/com/simibubi/create/content/logistics/IRedstoneLinkable.java b/src/main/java/com/simibubi/create/content/logistics/IRedstoneLinkable.java new file mode 100644 index 000000000..34286e6f6 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/IRedstoneLinkable.java @@ -0,0 +1,23 @@ +package com.simibubi.create.content.logistics; + +import org.apache.commons.lang3.tuple.Pair; + +import com.simibubi.create.content.logistics.RedstoneLinkNetworkHandler.Frequency; + +import net.minecraft.util.math.BlockPos; + +public interface IRedstoneLinkable { + + public int getTransmittedStrength(); + + public void setReceivedStrength(int power); + + public boolean isListening(); + + public boolean isAlive(); + + public Pair getNetworkKey(); + + public BlockPos getLocation(); + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/RedstoneLinkNetworkHandler.java b/src/main/java/com/simibubi/create/content/logistics/RedstoneLinkNetworkHandler.java index 867a9edf5..38ab8b08c 100644 --- a/src/main/java/com/simibubi/create/content/logistics/RedstoneLinkNetworkHandler.java +++ b/src/main/java/com/simibubi/create/content/logistics/RedstoneLinkNetworkHandler.java @@ -18,11 +18,11 @@ import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; import net.minecraft.world.IWorld; -import net.minecraft.world.World; public class RedstoneLinkNetworkHandler { - static final Map, Set>> connections = new IdentityHashMap<>(); + static final Map, Set>> connections = + new IdentityHashMap<>(); public static class Frequency { public static final Frequency EMPTY = new Frequency(ItemStack.EMPTY); @@ -60,7 +60,7 @@ public class RedstoneLinkNetworkHandler { if (this == obj) return true; return obj instanceof Frequency ? ((Frequency) obj).item == item && ((Frequency) obj).color == color - : false; + : false; } } @@ -75,45 +75,40 @@ public class RedstoneLinkNetworkHandler { Create.LOGGER.debug("Removed Redstone Network Space for " + WorldHelper.getDimensionID(world)); } - public Set getNetworkOf(LinkBehaviour actor) { - Map, Set> networksInWorld = networksIn(actor.getWorld()); + public Set getNetworkOf(IWorld world, IRedstoneLinkable actor) { + Map, Set> networksInWorld = networksIn(world); Pair key = actor.getNetworkKey(); if (!networksInWorld.containsKey(key)) networksInWorld.put(key, new LinkedHashSet<>()); return networksInWorld.get(key); } - public void addToNetwork(LinkBehaviour actor) { - getNetworkOf(actor).add(actor); - updateNetworkOf(actor); + public void addToNetwork(IWorld world, IRedstoneLinkable actor) { + getNetworkOf(world, actor).add(actor); + updateNetworkOf(world, actor); } - public void removeFromNetwork(LinkBehaviour actor) { - Set network = getNetworkOf(actor); + public void removeFromNetwork(IWorld world, IRedstoneLinkable actor) { + Set network = getNetworkOf(world, actor); network.remove(actor); if (network.isEmpty()) { - networksIn(actor.getWorld()).remove(actor.getNetworkKey()); + networksIn(world).remove(actor.getNetworkKey()); return; } - updateNetworkOf(actor); + updateNetworkOf(world, actor); } - public void updateNetworkOf(LinkBehaviour actor) { - Set network = getNetworkOf(actor); + public void updateNetworkOf(IWorld world, IRedstoneLinkable actor) { + Set network = getNetworkOf(world, actor); int power = 0; - for (Iterator iterator = network.iterator(); iterator.hasNext();) { - LinkBehaviour other = iterator.next(); - if (other.tileEntity.isRemoved()) { + for (Iterator iterator = network.iterator(); iterator.hasNext();) { + IRedstoneLinkable other = iterator.next(); + if (!other.isAlive()) { iterator.remove(); continue; } - World world = actor.getWorld(); - if (!world.isBlockPresent(other.tileEntity.getPos())) { - iterator.remove(); - continue; - } - if (world.getTileEntity(other.tileEntity.getPos()) != other.tileEntity) { + if (!world.isAreaLoaded(other.getLocation(), 0)) { iterator.remove(); continue; } @@ -124,28 +119,31 @@ public class RedstoneLinkNetworkHandler { power = Math.max(other.getTransmittedStrength(), power); } - // fix one-to-one loading order problem - if (actor.isListening()) { - actor.newPosition = true; - actor.updateReceiver(power); + if (actor instanceof LinkBehaviour) { + LinkBehaviour linkBehaviour = (LinkBehaviour) actor; + // fix one-to-one loading order problem + if (linkBehaviour.isListening()) { + linkBehaviour.newPosition = true; + linkBehaviour.setReceivedStrength(power); + } } - for (LinkBehaviour other : network) { + for (IRedstoneLinkable other : network) { if (other != actor && other.isListening() && withinRange(actor, other)) - other.updateReceiver(power); + other.setReceivedStrength(power); } } - public static boolean withinRange(LinkBehaviour from, LinkBehaviour to) { + public static boolean withinRange(IRedstoneLinkable from, IRedstoneLinkable to) { if (from == to) return true; - return from.getPos().withinDistance(to.getPos(), AllConfigs.SERVER.logistics.linkRange.get()); + return from.getLocation() + .withinDistance(to.getLocation(), AllConfigs.SERVER.logistics.linkRange.get()); } - public Map, Set> networksIn(IWorld world) { + public Map, Set> networksIn(IWorld world) { if (!connections.containsKey(world)) { - Create.LOGGER.warn( - "Tried to Access unprepared network space of " + WorldHelper.getDimensionID(world)); + Create.LOGGER.warn("Tried to Access unprepared network space of " + WorldHelper.getDimensionID(world)); return new HashMap<>(); } return connections.get(world); diff --git a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerBindPacket.java b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerBindPacket.java new file mode 100644 index 000000000..c3c7cc060 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerBindPacket.java @@ -0,0 +1,55 @@ +package com.simibubi.create.content.logistics.item; + +import org.apache.commons.lang3.tuple.Pair; + +import com.simibubi.create.content.logistics.RedstoneLinkNetworkHandler.Frequency; +import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; +import com.simibubi.create.foundation.tileEntity.behaviour.linked.LinkBehaviour; + +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.network.PacketBuffer; +import net.minecraft.util.math.BlockPos; +import net.minecraftforge.items.ItemStackHandler; + +public class LinkedControllerBindPacket extends LinkedControllerPacketBase { + + private int button; + private BlockPos linkLocation; + + public LinkedControllerBindPacket(int button, BlockPos linkLocation) { + this.button = button; + this.linkLocation = linkLocation; + } + + public LinkedControllerBindPacket(PacketBuffer buffer) { + this.button = buffer.readVarInt(); + this.linkLocation = buffer.readBlockPos(); + } + + @Override + public void write(PacketBuffer buffer) { + buffer.writeVarInt(button); + buffer.writeBlockPos(linkLocation); + } + + @Override + protected void handle(ServerPlayerEntity player, ItemStack heldItem) { + ItemStackHandler frequencyItems = LinkedControllerItem.getFrequencyItems(heldItem); + LinkBehaviour linkBehaviour = TileEntityBehaviour.get(player.world, linkLocation, LinkBehaviour.TYPE); + if (linkBehaviour == null) + return; + + Pair pair = linkBehaviour.getNetworkKey(); + frequencyItems.setStackInSlot(button * 2, pair.getKey() + .getStack() + .copy()); + frequencyItems.setStackInSlot(button * 2 + 1, pair.getValue() + .getStack() + .copy()); + + heldItem.getTag() + .put("Items", frequencyItems.serializeNBT()); + } + +} 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 new file mode 100644 index 000000000..d37eb293a --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerClientHandler.java @@ -0,0 +1,225 @@ +package com.simibubi.create.content.logistics.item; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Vector; + +import org.lwjgl.glfw.GLFW; + +import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.AllItems; +import com.simibubi.create.CreateClient; +import com.simibubi.create.content.contraptions.goggles.GoggleOverlayRenderer.TooltipScreen; +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.Lang; + +import net.minecraft.client.GameSettings; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.player.ClientPlayerEntity; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.renderer.IRenderTypeBuffer; +import net.minecraft.client.settings.KeyBinding; +import net.minecraft.client.util.InputMappings; +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.shapes.VoxelShape; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.TextFormatting; + +public class LinkedControllerClientHandler { + + enum Mode { + IDLE, ACTIVE, BIND + } + + public static Mode MODE = Mode.IDLE; + public static int PACKET_RATE = 5; + public static Collection currentlyPressed = new HashSet<>(); + private static BlockPos selectedLocation = BlockPos.ZERO; + private static Vector controls; + + private static int packetCooldown; + + public static Vector getControls() { + if (controls == null) { + GameSettings gameSettings = Minecraft.getInstance().gameSettings; + controls = new Vector<>(6); + controls.add(gameSettings.keyBindForward); + controls.add(gameSettings.keyBindBack); + controls.add(gameSettings.keyBindLeft); + controls.add(gameSettings.keyBindRight); + controls.add(gameSettings.keyBindJump); + controls.add(gameSettings.keySneak); + } + return controls; + } + + public static void toggleBindMode(BlockPos location) { + if (MODE == Mode.IDLE) { + MODE = Mode.BIND; + selectedLocation = location; + } else { + MODE = Mode.IDLE; + onReset(); + } + } + + public static void toggle() { + if (MODE == Mode.IDLE) + MODE = Mode.ACTIVE; + else { + MODE = Mode.IDLE; + onReset(); + } + } + + protected static void onReset() { + getControls().forEach(kb -> kb.setPressed(isActuallyPressed(kb))); + packetCooldown = 0; + selectedLocation = BlockPos.ZERO; + + if (!currentlyPressed.isEmpty()) + AllPackets.channel.sendToServer(new LinkedControllerInputPacket(currentlyPressed, false)); + currentlyPressed.clear(); + } + + protected static boolean isActuallyPressed(KeyBinding kb) { + return InputMappings.isKeyDown(Minecraft.getInstance() + .getWindow() + .getHandle(), + kb.getKey() + .getKeyCode()); + } + + public static void tick() { + LinkedControllerItemRenderer.tick(); + if (MODE == Mode.IDLE) + return; + if (packetCooldown > 0) + packetCooldown--; + + Minecraft mc = Minecraft.getInstance(); + ClientPlayerEntity player = mc.player; + ItemStack heldItem = player.getHeldItemMainhand(); + + if (mc.gameSettings.keyBindInventory.isPressed() || InputMappings.isKeyDown(mc.getWindow() + .getHandle(), GLFW.GLFW_KEY_ESCAPE)) { + MODE = Mode.IDLE; + onReset(); + return; + } + + if (!AllItems.LINKED_CONTROLLER.isIn(heldItem)) { + heldItem = player.getHeldItemOffhand(); + if (!AllItems.LINKED_CONTROLLER.isIn(heldItem)) { + MODE = Mode.IDLE; + onReset(); + return; + } + } + + Vector controls = getControls(); + Collection pressedKeys = new HashSet<>(); + for (int i = 0; i < controls.size(); i++) { + if (isActuallyPressed(controls.get(i))) + pressedKeys.add(i); + } + + Collection newKeys = new HashSet<>(pressedKeys); + Collection releasedKeys = currentlyPressed; + newKeys.removeAll(releasedKeys); + releasedKeys.removeAll(pressedKeys); + + if (MODE == Mode.ACTIVE) { + // Released Keys + if (!releasedKeys.isEmpty()) + AllPackets.channel.sendToServer(new LinkedControllerInputPacket(releasedKeys, false)); + + // Newly Pressed Keys + if (!newKeys.isEmpty()) { + AllPackets.channel.sendToServer(new LinkedControllerInputPacket(newKeys, true)); + packetCooldown = PACKET_RATE; + } + + // Keepalive Pressed Keys + if (packetCooldown == 0) { + if (!pressedKeys.isEmpty()) { + AllPackets.channel.sendToServer(new LinkedControllerInputPacket(pressedKeys, true)); + packetCooldown = PACKET_RATE; + } + } + } + + if (MODE == Mode.BIND) { + VoxelShape shape = mc.world.getBlockState(selectedLocation) + .getShape(mc.world, selectedLocation); + if (!shape.isEmpty()) + CreateClient.OUTLINER.showAABB("controller", shape.getBoundingBox() + .offset(selectedLocation)) + .colored(0xB73C2D) + .lineWidth(1 / 16f); + + for (Integer integer : newKeys) { + LinkBehaviour linkBehaviour = TileEntityBehaviour.get(mc.world, selectedLocation, LinkBehaviour.TYPE); + if (linkBehaviour != null) { + AllPackets.channel.sendToServer(new LinkedControllerBindPacket(integer, selectedLocation)); + Lang.sendStatus(mc.player, "linked_controller.key_bound", controls.get(integer) + .getBoundKeyLocalizedText() + .getString()); + } + MODE = Mode.IDLE; + break; + } + } + + currentlyPressed = pressedKeys; + controls.forEach(kb -> kb.setPressed(false)); + } + + public static void renderOverlay(MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay, + float partialTicks) { + if (MODE != Mode.BIND) + return; + Minecraft mc = Minecraft.getInstance(); + + ms.push(); + Screen tooltipScreen = new TooltipScreen(null); + tooltipScreen.init(mc, mc.getWindow() + .getScaledWidth(), + mc.getWindow() + .getScaledHeight()); + + Object[] keys = new Object[6]; + Vector controls = getControls(); + for (int i = 0; i < controls.size(); i++) { + KeyBinding keyBinding = controls.get(i); + keys[i] = keyBinding.getBoundKeyLocalizedText() + .getString(); + } + + List list = new ArrayList<>(); + list.add(Lang.createTranslationTextComponent("linked_controller.bind_mode") + .formatted(TextFormatting.GOLD)); + list.addAll( + TooltipHelper.cutTextComponent(Lang.createTranslationTextComponent("linked_controller.press_keybind", keys), + TextFormatting.GRAY, TextFormatting.GRAY)); + + int width = 0; + int height = list.size() * mc.fontRenderer.FONT_HEIGHT; + for (ITextComponent iTextComponent : list) + width = Math.max(width, mc.fontRenderer.getWidth(iTextComponent)); + int x = (tooltipScreen.width / 3) - width / 2; + int y = tooltipScreen.height - height; + + tooltipScreen.renderTooltip(ms, list, x, y); + + ms.pop(); + + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerContainer.java b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerContainer.java new file mode 100644 index 000000000..5f834d46b --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerContainer.java @@ -0,0 +1,152 @@ +package com.simibubi.create.content.logistics.item; + +import com.simibubi.create.foundation.gui.IClearableContainer; + +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.inventory.container.ClickType; +import net.minecraft.inventory.container.Container; +import net.minecraft.inventory.container.ContainerType; +import net.minecraft.inventory.container.Slot; +import net.minecraft.item.ItemStack; +import net.minecraft.network.PacketBuffer; +import net.minecraftforge.items.ItemStackHandler; +import net.minecraftforge.items.SlotItemHandler; + +public class LinkedControllerContainer extends Container implements IClearableContainer { + + public PlayerEntity player; + protected PlayerInventory playerInventory; + public ItemStack mainItem; + public ItemStackHandler filterInventory; + + public LinkedControllerContainer(ContainerType type, int id, PlayerInventory inv, PacketBuffer extraData) { + this(type, id, inv, extraData.readItemStack()); + } + + public LinkedControllerContainer(ContainerType type, int id, PlayerInventory inv, ItemStack filterItem) { + super(type, id); + player = inv.player; + playerInventory = inv; + this.mainItem = filterItem; + init(); + } + + protected void init() { + this.filterInventory = createFilterInventory(); +// readData(mainItem); + addPlayerSlots(); + addLinkSlots(); + detectAndSendChanges(); + } + + @Override + public void clearContents() { + for (int i = 0; i < filterInventory.getSlots(); i++) + filterInventory.setStackInSlot(i, ItemStack.EMPTY); + } + + protected void addPlayerSlots() { + int x = 22; + int y = 142; + + for (int hotbarSlot = 0; hotbarSlot < 9; ++hotbarSlot) + this.addSlot(new Slot(playerInventory, hotbarSlot, x + hotbarSlot * 18, y + 58)); + for (int row = 0; row < 3; ++row) + for (int col = 0; col < 9; ++col) + this.addSlot(new Slot(playerInventory, col + row * 9 + 9, x + col * 18, y + row * 18)); + } + + protected void addLinkSlots() { + int slot = 0; + int x = 12; + int y = 44; + + for (int column = 0; column < 6; column++) { + for (int row = 0; row < 2; ++row) + addSlot(new SlotItemHandler(filterInventory, slot++, x, y + row * 18)); + x += 24; + if (column == 3) + x += 11; + } + } + + @Override + public boolean canMergeSlot(ItemStack stack, Slot slotIn) { + return canDragIntoSlot(slotIn); + } + + @Override + public boolean canDragIntoSlot(Slot slotIn) { + return slotIn.inventory == playerInventory; + } + + @Override + public boolean canInteractWith(PlayerEntity playerIn) { + return true; + } + + @Override + public ItemStack slotClick(int slotId, int dragType, ClickType clickTypeIn, PlayerEntity player) { + if (slotId == playerInventory.currentItem && clickTypeIn != ClickType.THROW) + return ItemStack.EMPTY; + + ItemStack held = playerInventory.getItemStack(); + if (slotId < 36) + return super.slotClick(slotId, dragType, clickTypeIn, player); + if (clickTypeIn == ClickType.THROW) + return ItemStack.EMPTY; + + int slot = slotId - 36; + if (clickTypeIn == ClickType.CLONE) { + if (player.isCreative() && held.isEmpty()) { + ItemStack stackInSlot = filterInventory.getStackInSlot(slot) + .copy(); + stackInSlot.setCount(64); + playerInventory.setItemStack(stackInSlot); + return ItemStack.EMPTY; + } + return ItemStack.EMPTY; + } + + if (held.isEmpty()) { + filterInventory.setStackInSlot(slot, ItemStack.EMPTY); + return ItemStack.EMPTY; + } + + ItemStack insert = held.copy(); + insert.setCount(1); + filterInventory.setStackInSlot(slot, insert); + return held; + } + + protected ItemStackHandler createFilterInventory() { + return LinkedControllerItem.getFrequencyItems(mainItem); + } + + @Override + public ItemStack transferStackInSlot(PlayerEntity playerIn, int index) { + if (index < 36) { + ItemStack stackToInsert = playerInventory.getStackInSlot(index); + for (int i = 0; i < filterInventory.getSlots(); i++) { + ItemStack stack = filterInventory.getStackInSlot(i); + if (stack.isEmpty()) { + ItemStack copy = stackToInsert.copy(); + copy.setCount(1); + filterInventory.insertItem(i, copy, false); + break; + } + } + } else + filterInventory.extractItem(index - 36, 1, false); + return ItemStack.EMPTY; + } + + @Override + public void onContainerClosed(PlayerEntity playerIn) { + super.onContainerClosed(playerIn); + mainItem.getOrCreateTag() + .put("Items", filterInventory.serializeNBT()); +// saveData(filterItem); + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerInputPacket.java b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerInputPacket.java new file mode 100644 index 000000000..7d70ed4f9 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerInputPacket.java @@ -0,0 +1,50 @@ +package com.simibubi.create.content.logistics.item; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.UUID; +import java.util.stream.Collectors; + +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.network.PacketBuffer; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +public class LinkedControllerInputPacket extends LinkedControllerPacketBase { + + private Collection activatedButtons; + private boolean press; + + public LinkedControllerInputPacket(Collection activatedButtons, boolean press) { + this.activatedButtons = activatedButtons; + this.press = press; + } + + public LinkedControllerInputPacket(PacketBuffer buffer) { + activatedButtons = new ArrayList<>(); + press = buffer.readBoolean(); + int size = buffer.readVarInt(); + for (int i = 0; i < size; i++) + activatedButtons.add(buffer.readVarInt()); + } + + @Override + public void write(PacketBuffer buffer) { + buffer.writeBoolean(press); + buffer.writeVarInt(activatedButtons.size()); + activatedButtons.forEach(buffer::writeVarInt); + } + + @Override + protected void handle(ServerPlayerEntity player, ItemStack heldItem) { + World world = player.getEntityWorld(); + UUID uniqueID = player.getUniqueID(); + BlockPos pos = player.getBlockPos(); + + LinkedControllerServerHandler.receivePressed(world, pos, uniqueID, activatedButtons.stream() + .map(i -> LinkedControllerItem.toFrequency(heldItem, i)) + .collect(Collectors.toList()), press); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerItem.java b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerItem.java new file mode 100644 index 000000000..882c3bcc7 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerItem.java @@ -0,0 +1,116 @@ +package com.simibubi.create.content.logistics.item; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllContainerTypes; +import com.simibubi.create.AllItems; +import com.simibubi.create.content.logistics.RedstoneLinkNetworkHandler; +import com.simibubi.create.content.logistics.RedstoneLinkNetworkHandler.Frequency; +import com.simibubi.create.foundation.utility.Couple; + +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.inventory.container.Container; +import net.minecraft.inventory.container.INamedContainerProvider; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.item.ItemUseContext; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.util.ActionResult; +import net.minecraft.util.ActionResultType; +import net.minecraft.util.Hand; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.TranslationTextComponent; +import net.minecraft.world.World; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.fml.DistExecutor; +import net.minecraftforge.fml.network.NetworkHooks; +import net.minecraftforge.items.ItemStackHandler; + +public class LinkedControllerItem extends Item implements INamedContainerProvider { + + public LinkedControllerItem(Properties p_i48487_1_) { + super(p_i48487_1_); + } + + @Override + public ActionResultType onItemUse(ItemUseContext ctx) { + PlayerEntity player = ctx.getPlayer(); + if (player == null) + return ActionResultType.PASS; + World world = ctx.getWorld(); + + if (!player.isSneaking() && player.isAllowEdit() + && AllBlocks.REDSTONE_LINK.has(world.getBlockState(ctx.getPos()))) { + if (world.isRemote) + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> this.toggleBindMode(ctx.getPos())); + player.getCooldownTracker() + .setCooldown(this, 2); + return ActionResultType.SUCCESS; + } + + return onItemRightClick(world, player, ctx.getHand()).getType(); + } + + @Override + public ActionResult onItemRightClick(World world, PlayerEntity player, Hand hand) { + ItemStack heldItem = player.getHeldItem(hand); + + if (player.isSneaking() && hand == Hand.MAIN_HAND) { + if (!world.isRemote && player instanceof ServerPlayerEntity && player.isAllowEdit()) + NetworkHooks.openGui((ServerPlayerEntity) player, this, buf -> { + buf.writeItemStack(heldItem); + }); + return ActionResult.success(heldItem); + } + + if (!player.isSneaking()) { + if (world.isRemote) + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> this::toggleActive); + player.getCooldownTracker() + .setCooldown(this, 2); + } + + return ActionResult.pass(heldItem); + } + + @OnlyIn(Dist.CLIENT) + private void toggleBindMode(BlockPos pos) { + LinkedControllerClientHandler.toggleBindMode(pos); + } + + @OnlyIn(Dist.CLIENT) + private void toggleActive() { + LinkedControllerClientHandler.toggle(); + } + + public static ItemStackHandler getFrequencyItems(ItemStack stack) { + ItemStackHandler newInv = new ItemStackHandler(12); + if (AllItems.LINKED_CONTROLLER.get() != stack.getItem()) + throw new IllegalArgumentException("Cannot get frequency items from non-controller: " + stack); + CompoundNBT invNBT = stack.getOrCreateChildTag("Items"); + if (!invNBT.isEmpty()) + newInv.deserializeNBT(invNBT); + return newInv; + } + + public static Couple toFrequency(ItemStack controller, int slot) { + ItemStackHandler frequencyItems = getFrequencyItems(controller); + return Couple.create(Frequency.of(frequencyItems.getStackInSlot(slot * 2)), + Frequency.of(frequencyItems.getStackInSlot(slot * 2 + 1))); + } + + @Override + public Container createMenu(int id, PlayerInventory inv, PlayerEntity player) { + ItemStack heldItem = player.getHeldItemMainhand(); + return new LinkedControllerContainer(AllContainerTypes.LINKED_CONTROLLER.get(), id, inv, heldItem); + } + + @Override + public ITextComponent getDisplayName() { + return new TranslationTextComponent(getTranslationKey()); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerItemRenderer.java b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerItemRenderer.java new file mode 100644 index 000000000..2155442ec --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerItemRenderer.java @@ -0,0 +1,134 @@ +package com.simibubi.create.content.logistics.item; + +import java.util.Vector; + +import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.AllItems; +import com.simibubi.create.content.logistics.item.LinkedControllerClientHandler.Mode; +import com.simibubi.create.foundation.block.render.CustomRenderedItemModelRenderer; +import com.simibubi.create.foundation.item.PartialItemModelRenderer; +import com.simibubi.create.foundation.utility.AnimationTickHolder; +import com.simibubi.create.foundation.utility.MatrixStacker; +import com.simibubi.create.foundation.utility.animation.LerpedFloat; +import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.IRenderTypeBuffer; +import net.minecraft.client.renderer.model.IBakedModel; +import net.minecraft.client.renderer.model.ItemCameraTransforms; +import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType; +import net.minecraft.item.ItemStack; +import net.minecraft.util.HandSide; +import net.minecraft.util.math.MathHelper; + +public class LinkedControllerItemRenderer extends CustomRenderedItemModelRenderer { + + static LerpedFloat equipProgress; + static Vector buttons; + + static { + equipProgress = LerpedFloat.linear() + .startWithValue(0); + buttons = new Vector<>(6); + for (int i = 0; i < 6; i++) + buttons.add(LerpedFloat.linear() + .startWithValue(0)); + } + + static void tick() { + boolean active = LinkedControllerClientHandler.MODE != Mode.IDLE; + equipProgress.chase(active ? 1 : 0, .2f, Chaser.EXP); + equipProgress.tickChaser(); + + if (!active) + return; + + for (int i = 0; i < buttons.size(); i++) { + LerpedFloat lerpedFloat = buttons.get(i); + lerpedFloat.chase(LinkedControllerClientHandler.currentlyPressed.contains(i) ? 1 : 0, .4f, Chaser.EXP); + lerpedFloat.tickChaser(); + } + } + + @Override + protected void render(ItemStack stack, LinkedControllerModel model, PartialItemModelRenderer renderer, + ItemCameraTransforms.TransformType transformType, MatrixStack ms, IRenderTypeBuffer buffer, int light, + int overlay) { + float pt = AnimationTickHolder.getPartialTicks(); + MatrixStacker msr = MatrixStacker.of(ms); + + ms.push(); + + Minecraft mc = Minecraft.getInstance(); + boolean rightHanded = mc.gameSettings.mainHand == HandSide.RIGHT; + TransformType mainHand = + rightHanded ? TransformType.FIRST_PERSON_RIGHT_HAND : TransformType.FIRST_PERSON_LEFT_HAND; + TransformType offHand = + rightHanded ? TransformType.FIRST_PERSON_LEFT_HAND : TransformType.FIRST_PERSON_RIGHT_HAND; + + boolean active = false; + boolean noControllerInMain = !AllItems.LINKED_CONTROLLER.isIn(mc.player.getHeldItemMainhand()); + + if (transformType == mainHand || (transformType == offHand && noControllerInMain)) { + float equip = equipProgress.getValue(pt); + int handModifier = transformType == TransformType.FIRST_PERSON_LEFT_HAND ? -1 : 1; + msr.translate(0, equip / 4, equip / 4 * handModifier); + msr.rotateY(equip * -30 * handModifier); + msr.rotateZ(equip * -30); + active = true; + } + + if (transformType == TransformType.GUI) { + if (stack == mc.player.getHeldItemMainhand()) + active = true; + if (stack == mc.player.getHeldItemOffhand() && noControllerInMain) + active = true; + } + + active &= LinkedControllerClientHandler.MODE != Mode.IDLE; + renderer.render(active ? model.getPartial("powered") : model.getOriginalModel(), light); + + if (!active) { + ms.pop(); + return; + } + + IBakedModel button = model.getPartial("button"); + float s = 1 / 16f; + float b = s * -.75f; + int index = 0; + + if (LinkedControllerClientHandler.MODE == Mode.BIND) { + int i = (int) MathHelper.lerp((MathHelper.sin(AnimationTickHolder.getRenderTime() / 4f) + 1) / 2, 5, 15); + light = i << 20; + } + + ms.push(); + msr.translate(2 * s, 0, 8 * s); + button(renderer, ms, light, pt, button, b, index++); + msr.translate(4 * s, 0, 0); + button(renderer, ms, light, pt, button, b, index++); + msr.translate(-2 * s, 0, 2 * s); + button(renderer, ms, light, pt, button, b, index++); + msr.translate(0, 0, -4 * s); + button(renderer, ms, light, pt, button, b, index++); + ms.pop(); + + msr.translate(3 * s, 0, 3 * s); + button(renderer, ms, light, pt, button, b, index++); + msr.translate(2 * s, 0, 0); + button(renderer, ms, light, pt, button, b, index++); + + ms.pop(); + } + + protected void button(PartialItemModelRenderer renderer, MatrixStack ms, int light, float pt, IBakedModel button, + float b, int index) { + ms.push(); + ms.translate(0, b * buttons.get(index) + .getValue(pt), 0); + renderer.renderSolid(button, light); + ms.pop(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerModel.java b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerModel.java new file mode 100644 index 000000000..075880dfd --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerModel.java @@ -0,0 +1,20 @@ +package com.simibubi.create.content.logistics.item; + +import com.simibubi.create.foundation.block.render.CustomRenderedItemModel; + +import net.minecraft.client.renderer.model.IBakedModel; +import net.minecraft.client.renderer.tileentity.ItemStackTileEntityRenderer; + +public class LinkedControllerModel extends CustomRenderedItemModel { + + public LinkedControllerModel(IBakedModel template) { + super(template, "linked_controller"); + addPartials("powered", "button"); + } + + @Override + public ItemStackTileEntityRenderer createRenderer() { + return new LinkedControllerItemRenderer(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerPacketBase.java b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerPacketBase.java new file mode 100644 index 000000000..bbc5918c4 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerPacketBase.java @@ -0,0 +1,37 @@ +package com.simibubi.create.content.logistics.item; + +import java.util.function.Supplier; + +import com.simibubi.create.AllItems; +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraftforge.fml.network.NetworkEvent.Context; + +public abstract class LinkedControllerPacketBase extends SimplePacketBase { + + @Override + public void handle(Supplier context) { + context.get() + .enqueueWork(() -> { + ServerPlayerEntity player = context.get() + .getSender(); + if (player == null) + return; + + ItemStack heldItem = player.getHeldItemMainhand(); + if (!AllItems.LINKED_CONTROLLER.isIn(heldItem)) { + heldItem = player.getHeldItemOffhand(); + if (!AllItems.LINKED_CONTROLLER.isIn(heldItem)) + return; + } + handle(player, heldItem); + }); + context.get() + .setPacketHandled(true); + } + + protected abstract void handle(ServerPlayerEntity player, ItemStack heldItem); + +} 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 new file mode 100644 index 000000000..24a7acab3 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerScreen.java @@ -0,0 +1,134 @@ +package com.simibubi.create.content.logistics.item; + +import static com.simibubi.create.foundation.gui.AllGuiTextures.PLAYER_INVENTORY; + +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +import com.google.common.collect.ImmutableList; +import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.foundation.gui.AbstractSimiContainerScreen; +import com.simibubi.create.foundation.gui.AllGuiTextures; +import com.simibubi.create.foundation.gui.AllIcons; +import com.simibubi.create.foundation.gui.GuiGameElement; +import com.simibubi.create.foundation.gui.widgets.IconButton; +import com.simibubi.create.foundation.utility.Lang; + +import net.minecraft.client.renderer.Rectangle2d; +import net.minecraft.client.resources.I18n; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.TextFormatting; + +public class LinkedControllerScreen extends AbstractSimiContainerScreen { + + protected AllGuiTextures background; + private List extraAreas = Collections.emptyList(); + + private IconButton resetButton; + private IconButton confirmButton; + + public LinkedControllerScreen(LinkedControllerContainer container, PlayerInventory inv, ITextComponent title) { + super(container, inv, title); + this.background = AllGuiTextures.LINKED_CONTROLLER; + } + + @Override + protected void drawMouseoverTooltip(MatrixStack ms, int x, int y) { + if (!this.client.player.inventory.getItemStack() + .isEmpty() || this.hoveredSlot == null || this.hoveredSlot.getHasStack()) { + super.drawMouseoverTooltip(ms, x, y); + return; + } + renderWrappedToolTip(ms, addToTooltip(new LinkedList<>(), hoveredSlot.getSlotIndex()), x, y, textRenderer); + } + + @Override + public List getTooltipFromItem(ItemStack stack) { + List list = super.getTooltipFromItem(stack); + return hoveredSlot != null ? addToTooltip(list, hoveredSlot.getSlotIndex()) : list; + } + + private List addToTooltip(List list, int slot) { + if (slot < 0 || slot >= 12) + return list; + list.add(Lang + .createTranslationTextComponent("linked_controller.frequency_slot_" + ((slot % 2) + 1), + LinkedControllerClientHandler.getControls() + .get(slot / 2) + .getBoundKeyLocalizedText() + .getString()) + .formatted(TextFormatting.GOLD)); + return list; + } + + @Override + protected void init() { + setWindowSize(PLAYER_INVENTORY.width + 50, background.height + PLAYER_INVENTORY.height + 20); + super.init(); + widgets.clear(); + int x = guiLeft - 50; + int offset = guiTop < 30 ? 30 - guiTop : 0; + extraAreas = + ImmutableList.of(new Rectangle2d(x, guiTop + offset, background.width + 70, background.height - offset)); + + resetButton = new IconButton(x + background.width - 12, guiTop + background.height - 14, AllIcons.I_TRASH); + confirmButton = new IconButton(x + background.width + 16, guiTop + background.height - 14, AllIcons.I_CONFIRM); + + widgets.add(resetButton); + widgets.add(confirmButton); + } + + @Override + protected void renderWindow(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { + int x = guiLeft; + int y = guiTop + 10; + background.draw(ms, this, x, y); + + int invX = guiLeft + 14; + int invY = y + background.height + 5; + PLAYER_INVENTORY.draw(ms, this, invX, invY); + textRenderer.draw(ms, playerInventory.getDisplayName(), invX + 7, invY + 6, 0x666666); + textRenderer.draw(ms, I18n.format(container.mainItem.getTranslationKey()), x + 15, y + 4, 0x442000); + + GuiGameElement.of(container.mainItem).at(x + background.width - 8, guiTop + background.height - 53, -200) + .scale(5) + .render(ms); + + } + + @Override + public void tick() { + super.tick(); + if (!container.player.getHeldItemMainhand() + .equals(container.mainItem, false)) + client.player.closeScreen(); + } + + @Override + public boolean mouseClicked(double x, double y, int button) { + boolean mouseClicked = super.mouseClicked(x, y, button); + + if (button == 0) { + if (confirmButton.isHovered()) { + client.player.closeScreen(); + return true; + } + if (resetButton.isHovered()) { + container.clearContents(); + container.sendClearPacket(); + return true; + } + } + + return mouseClicked; + } + + @Override + public List getExtraAreas() { + return extraAreas; + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerServerHandler.java b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerServerHandler.java new file mode 100644 index 000000000..8e35e0cb6 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerServerHandler.java @@ -0,0 +1,123 @@ +package com.simibubi.create.content.logistics.item; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.UUID; + +import org.apache.commons.lang3.tuple.Pair; + +import com.simibubi.create.Create; +import com.simibubi.create.content.logistics.IRedstoneLinkable; +import com.simibubi.create.content.logistics.RedstoneLinkNetworkHandler.Frequency; +import com.simibubi.create.foundation.utility.Couple; +import com.simibubi.create.foundation.utility.IntAttached; +import com.simibubi.create.foundation.utility.WorldAttached; + +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IWorld; + +public class LinkedControllerServerHandler { + + public static WorldAttached>> receivedInputs = + new WorldAttached<>(HashMap::new); + static final int TIMEOUT = 30; + + public static void tick(IWorld world) { + Map> map = receivedInputs.get(world); + for (Iterator>> iterator = map.entrySet() + .iterator(); iterator.hasNext();) { + + Entry> entry = iterator.next(); + Collection list = entry.getValue(); + + for (Iterator entryIterator = list.iterator(); entryIterator.hasNext();) { + ManualFrequencyEntry manualFrequencyEntry = entryIterator.next(); + manualFrequencyEntry.decrement(); + if (!manualFrequencyEntry.isAlive()) { + Create.REDSTONE_LINK_NETWORK_HANDLER.removeFromNetwork(world, manualFrequencyEntry); + entryIterator.remove(); + } + } + + if (list.isEmpty()) + iterator.remove(); + } + } + + public static void receivePressed(IWorld world, BlockPos pos, UUID uniqueID, List> collect, + boolean pressed) { + Map> map = receivedInputs.get(world); + Collection list = map.computeIfAbsent(uniqueID, $ -> new ArrayList<>()); + + WithNext: for (Couple activated : collect) { + for (Iterator iterator = list.iterator(); iterator.hasNext();) { + ManualFrequencyEntry entry = iterator.next(); + if (entry.getSecond() + .equals(activated)) { + if (!pressed) + entry.setFirst(0); + else + entry.updatePosition(pos); + continue WithNext; + } + } + + if (!pressed) + continue; + + ManualFrequencyEntry entry = new ManualFrequencyEntry(pos, activated); + Create.REDSTONE_LINK_NETWORK_HANDLER.addToNetwork(world, entry); + list.add(entry); + } + } + + static class ManualFrequencyEntry extends IntAttached> implements IRedstoneLinkable { + + private BlockPos pos; + + public ManualFrequencyEntry(BlockPos pos, Couple second) { + super(TIMEOUT, second); + this.pos = pos; + } + + public void updatePosition(BlockPos pos) { + this.pos = pos; + setFirst(TIMEOUT); + } + + @Override + public int getTransmittedStrength() { + return isAlive() ? 15 : 0; + } + + @Override + public boolean isAlive() { + return getFirst() > 0; + } + + @Override + public BlockPos getLocation() { + return pos; + } + + @Override + public void setReceivedStrength(int power) {} + + @Override + public boolean isListening() { + return false; + } + + @Override + public Pair getNetworkKey() { + return Pair.of(getSecond().getFirst(), getSecond().getSecond()); + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/AbstractFilterContainer.java b/src/main/java/com/simibubi/create/content/logistics/item/filter/AbstractFilterContainer.java index 1bd54d34d..ef433e77e 100644 --- a/src/main/java/com/simibubi/create/content/logistics/item/filter/AbstractFilterContainer.java +++ b/src/main/java/com/simibubi/create/content/logistics/item/filter/AbstractFilterContainer.java @@ -1,5 +1,7 @@ package com.simibubi.create.content.logistics.item.filter; +import com.simibubi.create.foundation.gui.IClearableContainer; + import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.inventory.container.ClickType; @@ -11,7 +13,7 @@ import net.minecraft.network.PacketBuffer; import net.minecraftforge.items.ItemHandlerHelper; import net.minecraftforge.items.ItemStackHandler; -public abstract class AbstractFilterContainer extends Container { +public abstract class AbstractFilterContainer extends Container implements IClearableContainer { public PlayerEntity player; protected PlayerInventory playerInventory; @@ -38,7 +40,8 @@ public abstract class AbstractFilterContainer extends Container { detectAndSendChanges(); } - protected void clearContents() { + @Override + public void clearContents() { for (int i = 0; i < filterInventory.getSlots(); i++) filterInventory.setStackInSlot(i, ItemStack.EMPTY); } diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/AbstractFilterScreen.java b/src/main/java/com/simibubi/create/content/logistics/item/filter/AbstractFilterScreen.java index bade51cb0..de8703059 100644 --- a/src/main/java/com/simibubi/create/content/logistics/item/filter/AbstractFilterScreen.java +++ b/src/main/java/com/simibubi/create/content/logistics/item/filter/AbstractFilterScreen.java @@ -30,7 +30,7 @@ import net.minecraft.util.text.ITextComponent; public abstract class AbstractFilterScreen extends AbstractSimiContainerScreen { protected AllGuiTextures background; - private List extraAreas = Collections.EMPTY_LIST; + private List extraAreas = Collections.emptyList(); private IconButton resetButton; private IconButton confirmButton; @@ -146,7 +146,7 @@ public abstract class AbstractFilterScreen ex if (resetButton.isHovered()) { container.clearContents(); contentsCleared(); - sendOptionUpdate(Option.CLEAR); + container.sendClearPacket(); return true; } } diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/AttributeFilterContainer.java b/src/main/java/com/simibubi/create/content/logistics/item/filter/AttributeFilterContainer.java index 589f1a9e3..487f801d7 100644 --- a/src/main/java/com/simibubi/create/content/logistics/item/filter/AttributeFilterContainer.java +++ b/src/main/java/com/simibubi/create/content/logistics/item/filter/AttributeFilterContainer.java @@ -48,7 +48,7 @@ public class AttributeFilterContainer extends AbstractFilterContainer { } @Override - protected void clearContents() { + public void clearContents() { selectedAttributes.clear(); } diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/FilterScreenPacket.java b/src/main/java/com/simibubi/create/content/logistics/item/filter/FilterScreenPacket.java index 071baffa2..ac4b1c7a8 100644 --- a/src/main/java/com/simibubi/create/content/logistics/item/filter/FilterScreenPacket.java +++ b/src/main/java/com/simibubi/create/content/logistics/item/filter/FilterScreenPacket.java @@ -13,7 +13,7 @@ import net.minecraftforge.fml.network.NetworkEvent.Context; public class FilterScreenPacket extends SimplePacketBase { public enum Option { - CLEAR, WHITELIST, WHITELIST2, BLACKLIST, RESPECT_DATA, IGNORE_DATA, UPDATE_FILTER_ITEM, ADD_TAG, ADD_INVERTED_TAG; + WHITELIST, WHITELIST2, BLACKLIST, RESPECT_DATA, IGNORE_DATA, UPDATE_FILTER_ITEM, ADD_TAG, ADD_INVERTED_TAG; } private final Option option; @@ -46,14 +46,6 @@ public class FilterScreenPacket extends SimplePacketBase { if (player == null) return; - if (player.openContainer instanceof AbstractFilterContainer) { - AbstractFilterContainer c = (AbstractFilterContainer) player.openContainer; - if (option == Option.CLEAR) { - c.clearContents(); - return; - } - } - if (player.openContainer instanceof FilterContainer) { FilterContainer c = (FilterContainer) player.openContainer; if (option == Option.WHITELIST) diff --git a/src/main/java/com/simibubi/create/events/ClientEvents.java b/src/main/java/com/simibubi/create/events/ClientEvents.java index 37c126432..30db2de2a 100644 --- a/src/main/java/com/simibubi/create/events/ClientEvents.java +++ b/src/main/java/com/simibubi/create/events/ClientEvents.java @@ -30,6 +30,7 @@ import com.simibubi.create.content.curiosities.zapper.ZapperRenderHandler; import com.simibubi.create.content.curiosities.zapper.terrainzapper.WorldshaperRenderHandler; import com.simibubi.create.content.logistics.block.depot.EjectorTargetHandler; import com.simibubi.create.content.logistics.block.mechanicalArm.ArmInteractionPointHandler; +import com.simibubi.create.content.logistics.item.LinkedControllerClientHandler; import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.config.ui.BaseConfigScreen; import com.simibubi.create.foundation.fluid.FluidHelper; @@ -101,9 +102,11 @@ public class ClientEvents { return; if (event.phase == Phase.START) { + LinkedControllerClientHandler.tick(); AirCurrent.tickClientPlayerSounds(); return; } + SoundScapes.tick(); AnimationTickHolder.tick(); @@ -221,6 +224,7 @@ public class ClientEvents { public static void onRenderHotbar(MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay, float partialTicks) { CreateClient.SCHEMATIC_HANDLER.renderOverlay(ms, buffer, light, overlay, partialTicks); + LinkedControllerClientHandler.renderOverlay(ms, buffer, light, overlay, partialTicks); } @SubscribeEvent diff --git a/src/main/java/com/simibubi/create/events/CommonEvents.java b/src/main/java/com/simibubi/create/events/CommonEvents.java index 7fcd4f57a..6664931dd 100644 --- a/src/main/java/com/simibubi/create/events/CommonEvents.java +++ b/src/main/java/com/simibubi/create/events/CommonEvents.java @@ -10,6 +10,7 @@ import com.simibubi.create.content.contraptions.fluids.recipe.PotionMixingRecipe import com.simibubi.create.content.contraptions.wrench.WrenchItem; import com.simibubi.create.content.curiosities.zapper.ZapperInteractionHandler; import com.simibubi.create.content.curiosities.zapper.ZapperItem; +import com.simibubi.create.content.logistics.item.LinkedControllerServerHandler; import com.simibubi.create.foundation.command.AllCommands; import com.simibubi.create.foundation.fluid.FluidHelper; import com.simibubi.create.foundation.utility.Iterate; @@ -93,6 +94,7 @@ public class CommonEvents { ContraptionHandler.tick(world); CapabilityMinecartController.tick(world); CouplingPhysics.tick(world); + LinkedControllerServerHandler.tick(world); } @SubscribeEvent diff --git a/src/main/java/com/simibubi/create/foundation/gui/AllGuiTextures.java b/src/main/java/com/simibubi/create/foundation/gui/AllGuiTextures.java index db6fdea92..8055e15ce 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/AllGuiTextures.java +++ b/src/main/java/com/simibubi/create/foundation/gui/AllGuiTextures.java @@ -57,6 +57,8 @@ public enum AllGuiTextures implements IScreenRenderable { SEQUENCER_END("sequencer.png", 0, 80, 162, 22), SEQUENCER_EMPTY("sequencer.png", 0, 102, 162, 22), SEQUENCER_AWAIT("sequencer.png", 0, 160, 162, 22), + + LINKED_CONTROLLER("curiosities2.png", 180, 109), // JEI JEI_SLOT("jei/widgets.png", 18, 18), diff --git a/src/main/java/com/simibubi/create/foundation/gui/ClearContainerPacket.java b/src/main/java/com/simibubi/create/foundation/gui/ClearContainerPacket.java new file mode 100644 index 000000000..4714c273c --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/gui/ClearContainerPacket.java @@ -0,0 +1,36 @@ +package com.simibubi.create.foundation.gui; + +import java.util.function.Supplier; + +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.network.PacketBuffer; +import net.minecraftforge.fml.network.NetworkEvent.Context; + +public class ClearContainerPacket extends SimplePacketBase { + + public ClearContainerPacket() {} + + public ClearContainerPacket(PacketBuffer buffer) {} + + @Override + public void write(PacketBuffer buffer) {} + + @Override + public void handle(Supplier context) { + context.get() + .enqueueWork(() -> { + ServerPlayerEntity player = context.get() + .getSender(); + if (player == null) + return; + if (!(player.openContainer instanceof IClearableContainer)) + return; + ((IClearableContainer) player.openContainer).clearContents(); + }); + context.get() + .setPacketHandled(true); + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/gui/IClearableContainer.java b/src/main/java/com/simibubi/create/foundation/gui/IClearableContainer.java new file mode 100644 index 000000000..eea746881 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/gui/IClearableContainer.java @@ -0,0 +1,13 @@ +package com.simibubi.create.foundation.gui; + +import com.simibubi.create.foundation.networking.AllPackets; + +public interface IClearableContainer { + + default void sendClearPacket() { + AllPackets.channel.sendToServer(new ClearContainerPacket()); + } + + public void clearContents(); + +} diff --git a/src/main/java/com/simibubi/create/foundation/networking/AllPackets.java b/src/main/java/com/simibubi/create/foundation/networking/AllPackets.java index faa37475d..26cb098a5 100644 --- a/src/main/java/com/simibubi/create/foundation/networking/AllPackets.java +++ b/src/main/java/com/simibubi/create/foundation/networking/AllPackets.java @@ -28,6 +28,8 @@ import com.simibubi.create.content.logistics.block.depot.EjectorElytraPacket; import com.simibubi.create.content.logistics.block.depot.EjectorPlacementPacket; import com.simibubi.create.content.logistics.block.depot.EjectorTriggerPacket; import com.simibubi.create.content.logistics.block.mechanicalArm.ArmPlacementPacket; +import com.simibubi.create.content.logistics.item.LinkedControllerBindPacket; +import com.simibubi.create.content.logistics.item.LinkedControllerInputPacket; import com.simibubi.create.content.logistics.item.filter.FilterScreenPacket; import com.simibubi.create.content.logistics.packet.ConfigureFlexcratePacket; import com.simibubi.create.content.logistics.packet.ConfigureStockswitchPacket; @@ -38,9 +40,10 @@ import com.simibubi.create.content.schematics.packet.InstantSchematicPacket; import com.simibubi.create.content.schematics.packet.SchematicPlacePacket; import com.simibubi.create.content.schematics.packet.SchematicSyncPacket; import com.simibubi.create.content.schematics.packet.SchematicUploadPacket; -import com.simibubi.create.foundation.command.SConfigureConfigPacket; import com.simibubi.create.foundation.command.HighlightPacket; +import com.simibubi.create.foundation.command.SConfigureConfigPacket; import com.simibubi.create.foundation.config.ui.CConfigureConfigPacket; +import com.simibubi.create.foundation.gui.ClearContainerPacket; import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringCountUpdatePacket; import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueUpdatePacket; import com.simibubi.create.foundation.utility.ServerSpeedProvider; @@ -67,6 +70,7 @@ public enum AllPackets { PLAY_TO_SERVER), PLACE_SCHEMATIC(SchematicPlacePacket.class, SchematicPlacePacket::new, PLAY_TO_SERVER), UPLOAD_SCHEMATIC(SchematicUploadPacket.class, SchematicUploadPacket::new, PLAY_TO_SERVER), + CLEAR_CONTAINER(ClearContainerPacket.class, ClearContainerPacket::new, PLAY_TO_SERVER), CONFIGURE_FILTER(FilterScreenPacket.class, FilterScreenPacket::new, PLAY_TO_SERVER), CONFIGURE_FILTERING_AMOUNT(FilteringCountUpdatePacket.class, FilteringCountUpdatePacket::new, PLAY_TO_SERVER), CONFIGURE_SCROLLABLE(ScrollValueUpdatePacket.class, ScrollValueUpdatePacket::new, PLAY_TO_SERVER), @@ -81,6 +85,8 @@ public enum AllPackets { PLACE_EJECTOR(EjectorPlacementPacket.class, EjectorPlacementPacket::new, PLAY_TO_SERVER), TRIGGER_EJECTOR(EjectorTriggerPacket.class, EjectorTriggerPacket::new, PLAY_TO_SERVER), EJECTOR_ELYTRA(EjectorElytraPacket.class, EjectorElytraPacket::new, PLAY_TO_SERVER), + LINKED_CONTROLLER_INPUT(LinkedControllerInputPacket.class, LinkedControllerInputPacket::new, PLAY_TO_SERVER), + LINKED_CONTROLLER_BIND(LinkedControllerBindPacket.class, LinkedControllerBindPacket::new, PLAY_TO_SERVER), C_CONFIGURE_CONFIG(CConfigureConfigPacket.class, CConfigureConfigPacket::new, PLAY_TO_SERVER), // Server to Client diff --git a/src/main/java/com/simibubi/create/foundation/renderState/RenderTypes.java b/src/main/java/com/simibubi/create/foundation/renderState/RenderTypes.java index 31c129642..41cc284bd 100644 --- a/src/main/java/com/simibubi/create/foundation/renderState/RenderTypes.java +++ b/src/main/java/com/simibubi/create/foundation/renderState/RenderTypes.java @@ -83,7 +83,7 @@ public class RenderTypes extends RenderState { .transparency(TRANSLUCENT_TRANSPARENCY) .diffuseLighting(ENABLE_DIFFUSE_LIGHTING) .alpha(ONE_TENTH_ALPHA) - .cull(DISABLE_CULLING) + .cull(ENABLE_CULLING) .lightmap(ENABLE_LIGHTMAP) .overlay(ENABLE_OVERLAY_COLOR) .build(true)); diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/TileEntityBehaviour.java b/src/main/java/com/simibubi/create/foundation/tileEntity/TileEntityBehaviour.java index cfba21b6b..e7d0cfac9 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/TileEntityBehaviour.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/TileEntityBehaviour.java @@ -4,7 +4,6 @@ import com.simibubi.create.content.schematics.ItemRequirement; import com.simibubi.create.foundation.tileEntity.behaviour.BehaviourType; import net.minecraft.block.BlockState; -import net.minecraft.item.Item; import net.minecraft.nbt.CompoundNBT; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.BlockPos; diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/linked/LinkBehaviour.java b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/linked/LinkBehaviour.java index 9b9ef352d..75aa226e0 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/linked/LinkBehaviour.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/linked/LinkBehaviour.java @@ -7,6 +7,7 @@ import java.util.function.IntSupplier; import org.apache.commons.lang3.tuple.Pair; import com.simibubi.create.Create; +import com.simibubi.create.content.logistics.IRedstoneLinkable; import com.simibubi.create.content.logistics.RedstoneLinkNetworkHandler; import com.simibubi.create.content.logistics.RedstoneLinkNetworkHandler.Frequency; import com.simibubi.create.foundation.tileEntity.SmartTileEntity; @@ -17,9 +18,10 @@ import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform; import net.minecraft.block.BlockState; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.vector.Vector3d; -public class LinkBehaviour extends TileEntityBehaviour { +public class LinkBehaviour extends TileEntityBehaviour implements IRedstoneLinkable { public static BehaviourType TYPE = new BehaviourType<>(); @@ -76,33 +78,37 @@ public class LinkBehaviour extends TileEntityBehaviour { frequencyLast = behaviour.frequencyLast; } + @Override public boolean isListening() { return mode == Mode.RECEIVE; } + @Override public int getTransmittedStrength() { return mode == Mode.TRANSMIT ? transmission.getAsInt() : 0; } - public void updateReceiver(int networkPower) { + @Override + public void setReceivedStrength(int networkPower) { if (!newPosition) return; signalCallback.accept(networkPower); } public void notifySignalChange() { - Create.REDSTONE_LINK_NETWORK_HANDLER.updateNetworkOf(this); + Create.REDSTONE_LINK_NETWORK_HANDLER.updateNetworkOf(getWorld(), this); } @Override public void initialize() { super.initialize(); - if (tileEntity.getWorld().isRemote) + if (getWorld().isRemote) return; - getHandler().addToNetwork(this); + getHandler().addToNetwork(getWorld(), this); newPosition = true; } + @Override public Pair getNetworkKey() { return Pair.of(frequencyFirst, frequencyLast); } @@ -110,13 +116,15 @@ public class LinkBehaviour extends TileEntityBehaviour { @Override public void remove() { super.remove(); - if (tileEntity.getWorld().isRemote) + if (getWorld().isRemote) return; - getHandler().removeFromNetwork(this); + getHandler().removeFromNetwork(getWorld(), this); } @Override - public boolean isSafeNBT() { return true; } + public boolean isSafeNBT() { + return true; + } @Override public void write(CompoundNBT nbt, boolean clientPacket) { @@ -149,7 +157,7 @@ public class LinkBehaviour extends TileEntityBehaviour { !ItemStack.areItemsEqual(stack, toCompare) || !ItemStack.areItemStackTagsEqual(stack, toCompare); if (changed) - getHandler().removeFromNetwork(this); + getHandler().removeFromNetwork(getWorld(), this); if (first) frequencyFirst = Frequency.of(stack); @@ -160,7 +168,7 @@ public class LinkBehaviour extends TileEntityBehaviour { return; tileEntity.sendData(); - getHandler().addToNetwork(this); + getHandler().addToNetwork(getWorld(), this); } @Override @@ -197,4 +205,14 @@ public class LinkBehaviour extends TileEntityBehaviour { return (first ? firstSlot : secondSlot).testHit(state, localHit); } + @Override + public boolean isAlive() { + return !tileEntity.isRemoved() && getWorld().getTileEntity(getPos()) == tileEntity; + } + + @Override + public BlockPos getLocation() { + return getPos(); + } + } diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/linked/LinkHandler.java b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/linked/LinkHandler.java index 30a88de18..1c5e6319f 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/linked/LinkHandler.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/linked/LinkHandler.java @@ -2,10 +2,12 @@ package com.simibubi.create.foundation.tileEntity.behaviour.linked; import java.util.Arrays; +import com.simibubi.create.AllItems; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.utility.RaycastHelper; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; import net.minecraft.util.ActionResultType; import net.minecraft.util.Hand; import net.minecraft.util.SoundCategory; @@ -35,14 +37,19 @@ public class LinkHandler { if (behaviour == null) return; + ItemStack heldItem = player.getHeldItem(hand); BlockRayTraceResult ray = RaycastHelper.rayTraceRange(world, player, 10); if (ray == null) return; + if (AllItems.LINKED_CONTROLLER.isIn(heldItem)) + return; + if (AllItems.WRENCH.isIn(heldItem)) + return; for (boolean first : Arrays.asList(false, true)) { if (behaviour.testHit(first, ray.getHitVec())) { - if (event.getSide() != LogicalSide.CLIENT) - behaviour.setFrequency(first, player.getHeldItem(hand)); + if (event.getSide() != LogicalSide.CLIENT) + behaviour.setFrequency(first, heldItem); event.setCanceled(true); event.setCancellationResult(ActionResultType.SUCCESS); world.playSound(null, pos, SoundEvents.ENTITY_ITEM_FRAME_ADD_ITEM, SoundCategory.BLOCKS, .25f, .1f); diff --git a/src/main/resources/assets/create/lang/default/messages.json b/src/main/resources/assets/create/lang/default/messages.json index 22a691d46..ce2e8e7e6 100644 --- a/src/main/resources/assets/create/lang/default/messages.json +++ b/src/main/resources/assets/create/lang/default/messages.json @@ -464,6 +464,12 @@ "create.tooltip.chute.fans_pull_down": "Fans pull from Below", "create.tooltip.chute.contains": "Contains: %1$s x%2$s", + "create.linked_controller.bind_mode": "Bind mode active", + "create.linked_controller.press_keybind": "Press %1$s, %2$s, %3$s, %4$s, %5$s or %6$s, to bind this frequency to the respective key", + "create.linked_controller.key_bound": "Frequency bound to %1$s", + "create.linked_controller.frequency_slot_1": "Keybind: %1$s, Freq. #1", + "create.linked_controller.frequency_slot_2": "Keybind: %1$s, Freq. #2", + "create.hint.hose_pulley.title": "Bottomless Supply", "create.hint.hose_pulley": "The targeted body of fluid is considered infinite.", "create.hint.mechanical_arm_no_targets.title": "No Targets", diff --git a/src/main/resources/assets/create/models/item/linked_controller/button.json b/src/main/resources/assets/create/models/item/linked_controller/button.json new file mode 100644 index 000000000..9859c72ab --- /dev/null +++ b/src/main/resources/assets/create/models/item/linked_controller/button.json @@ -0,0 +1,22 @@ +{ + "credit": "Made with Blockbench", + "parent": "create:item/linked_controller/powered", + "textures": { + "particle": "create:item/linked_controller", + "redstone_bridge": "create:item/linked_controller" + }, + "elements": [ + { + "from": [3, 1, 0.5], + "to": [5, 3, 2.5], + "rotation": {"angle": 0, "axis": "y", "origin": [0, 0, 0.5]}, + "faces": { + "north": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "east": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "south": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "west": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "up": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/item/linked_controller/item.json b/src/main/resources/assets/create/models/item/linked_controller/item.json new file mode 100644 index 000000000..88c8e9cdc --- /dev/null +++ b/src/main/resources/assets/create/models/item/linked_controller/item.json @@ -0,0 +1,166 @@ +{ + "credit": "Made with Blockbench", + "parent": "block/block", + "textures": { + "redstone_antenna": "create:block/redstone_antenna", + "particle": "create:item/linked_controller", + "redstone_bridge": "create:item/linked_controller" + }, + "elements": [ + { + "name": "Controller", + "from": [4, 0, 1.5], + "to": [12, 2, 14.5], + "rotation": {"angle": 0, "axis": "y", "origin": [0, 0, 0.5]}, + "faces": { + "north": {"uv": [13, 0, 15, 8], "rotation": 90, "texture": "#redstone_bridge"}, + "east": {"uv": [0, 8, 13, 10], "texture": "#redstone_bridge"}, + "south": {"uv": [13, 0, 15, 8], "rotation": 90, "texture": "#redstone_bridge"}, + "west": {"uv": [0, 8, 13, 10], "texture": "#redstone_bridge"}, + "up": {"uv": [0, 0, 13, 8], "rotation": 270, "texture": "#redstone_bridge"}, + "down": {"uv": [0, 0, 13, 8], "rotation": 90, "texture": "#redstone_bridge"} + } + }, + { + "name": "AntennaTop", + "from": [3, 6, 4.5], + "to": [4, 7, 5.5], + "rotation": {"angle": 0, "axis": "z", "origin": [4, 2, 14.5]}, + "faces": { + "up": {"uv": [1, 1, 2, 2], "texture": "#redstone_antenna"} + } + }, + { + "name": "AntennaZ", + "from": [3, 0, 3.5], + "to": [4, 8, 6.5], + "rotation": {"angle": 0, "axis": "z", "origin": [4, 2, 14.5]}, + "faces": { + "east": {"uv": [0, 0, 3, 8], "texture": "#redstone_antenna"}, + "west": {"uv": [0, 0, 3, 8], "texture": "#redstone_antenna"} + } + }, + { + "name": "AntennaX", + "from": [2, 0, 4.5], + "to": [5, 8, 5.5], + "rotation": {"angle": 0, "axis": "z", "origin": [4, 2, 14.5]}, + "faces": { + "north": {"uv": [0, 0, 3, 8], "texture": "#redstone_antenna"}, + "south": {"uv": [0, 0, 3, 8], "texture": "#redstone_antenna"}, + "down": {"uv": [0, 9, 3, 10], "texture": "#redstone_antenna"} + } + }, + { + "from": [9, 1, 8.5], + "to": [11, 3, 10.5], + "rotation": {"angle": 0, "axis": "y", "origin": [0, 0, 0.5]}, + "faces": { + "north": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "east": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "south": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "west": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "up": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"} + } + }, + { + "from": [5, 1, 8.5], + "to": [7, 3, 10.5], + "rotation": {"angle": 0, "axis": "y", "origin": [0, 0, 0.5]}, + "faces": { + "north": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "east": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "south": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "west": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "up": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"} + } + }, + { + "from": [7, 1, 10.5], + "to": [9, 3, 12.5], + "rotation": {"angle": 0, "axis": "y", "origin": [0, 0, 0.5]}, + "faces": { + "north": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "east": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "south": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "west": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "up": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"} + } + }, + { + "from": [7, 1, 6.5], + "to": [9, 3, 8.5], + "rotation": {"angle": 0, "axis": "y", "origin": [0, 0, 0.5]}, + "faces": { + "north": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "east": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "south": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "west": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "up": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"} + } + }, + { + "from": [8, 1, 3.5], + "to": [10, 3, 5.5], + "rotation": {"angle": 0, "axis": "y", "origin": [0, 0, 0.5]}, + "faces": { + "north": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "east": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "south": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "west": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "up": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"} + } + }, + { + "from": [6, 1, 3.5], + "to": [8, 3, 5.5], + "rotation": {"angle": 0, "axis": "y", "origin": [0, 0, 0.5]}, + "faces": { + "north": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "east": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "south": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "west": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "up": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"} + } + } + ], + "display": { + "thirdperson_righthand": { + "rotation": [0, -90, -74], + "translation": [-3, 3.25, 4.5], + "scale": [0.7, 0.7, 0.7] + }, + "thirdperson_lefthand": { + "rotation": [0, 90, 74], + "translation": [-3, 3.5, 5], + "scale": [0.7, 0.7, 0.7] + }, + "firstperson_righthand": { + "rotation": [0, -90, -13], + "translation": [1.13, 3, 1.13], + "scale": [0.68, 0.68, 0.68] + }, + "firstperson_lefthand": { + "rotation": [0, 71, 17], + "translation": [1.13, 3, 1.13], + "scale": [0.68, 0.68, 0.68] + }, + "ground": { + "translation": [0, 3, 0], + "scale": [0.65, 0.65, 0.65] + }, + "gui": { + "rotation": [30, -44, 0], + "translation": [0, 3.5, 0], + "scale": [0.76, 0.76, 0.76] + }, + "head": { + "rotation": [0, 180, 0], + "translation": [0, 13, 0] + }, + "fixed": { + "rotation": [0, 90, -90], + "translation": [0, 0, -8] + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/item/linked_controller/powered.json b/src/main/resources/assets/create/models/item/linked_controller/powered.json new file mode 100644 index 000000000..1a747b4fa --- /dev/null +++ b/src/main/resources/assets/create/models/item/linked_controller/powered.json @@ -0,0 +1,94 @@ +{ + "credit": "Made with Blockbench", + "parent": "block/block", + "textures": { + "redstone_antenna": "create:block/redstone_antenna_powered", + "particle": "create:item/linked_controller_powered", + "redstone_bridge": "create:item/linked_controller_powered" + }, + "elements": [ + { + "name": "Controller", + "from": [4, 0, 1.5], + "to": [12, 2, 14.5], + "rotation": {"angle": 0, "axis": "y", "origin": [0, 0, 0.5]}, + "faces": { + "north": {"uv": [13, 0, 15, 8], "rotation": 90, "texture": "#redstone_bridge"}, + "east": {"uv": [0, 8, 13, 10], "texture": "#redstone_bridge"}, + "south": {"uv": [13, 0, 15, 8], "rotation": 90, "texture": "#redstone_bridge"}, + "west": {"uv": [0, 8, 13, 10], "texture": "#redstone_bridge"}, + "up": {"uv": [0, 0, 13, 8], "rotation": 270, "texture": "#redstone_bridge"}, + "down": {"uv": [0, 0, 13, 8], "rotation": 90, "texture": "#redstone_bridge"} + } + }, + { + "name": "AntennaTop", + "from": [3, 6, 4.5], + "to": [4, 7, 5.5], + "rotation": {"angle": 0, "axis": "z", "origin": [4, 2, 14.5]}, + "faces": { + "up": {"uv": [1, 1, 2, 2], "texture": "#redstone_antenna"} + } + }, + { + "name": "AntennaZ", + "from": [3, 0, 3.5], + "to": [4, 8, 6.5], + "rotation": {"angle": 0, "axis": "z", "origin": [4, 2, 14.5]}, + "faces": { + "east": {"uv": [0, 0, 3, 8], "texture": "#redstone_antenna"}, + "west": {"uv": [0, 0, 3, 8], "texture": "#redstone_antenna"} + } + }, + { + "name": "AntennaX", + "from": [2, 0, 4.5], + "to": [5, 8, 5.5], + "rotation": {"angle": 0, "axis": "z", "origin": [4, 2, 14.5]}, + "faces": { + "north": {"uv": [0, 0, 3, 8], "texture": "#redstone_antenna"}, + "south": {"uv": [0, 0, 3, 8], "texture": "#redstone_antenna"}, + "down": {"uv": [0, 9, 3, 10], "texture": "#redstone_antenna"} + } + } + ], + "display": { + "thirdperson_righthand": { + "rotation": [0, -90, -74], + "translation": [-3, 3.25, 4.5], + "scale": [0.7, 0.7, 0.7] + }, + "thirdperson_lefthand": { + "rotation": [0, 90, 74], + "translation": [-3, 3.5, 5], + "scale": [0.7, 0.7, 0.7] + }, + "firstperson_righthand": { + "rotation": [0, -113, -27], + "translation": [-2, 9, 1.13], + "scale": [0.97, 0.97, 0.97] + }, + "firstperson_lefthand": { + "rotation": [0, 47, 27], + "translation": [-2, 9, 1.13], + "scale": [0.97, 0.97, 0.97] + }, + "ground": { + "translation": [0, 2, 0], + "scale": [0.75, 0.75, 0.75] + }, + "gui": { + "rotation": [30, -44, 0], + "translation": [0, 1.75, 0], + "scale": [0.76, 0.76, 0.76] + }, + "head": { + "rotation": [0, 180, 0], + "translation": [0, 13, 0] + }, + "fixed": { + "rotation": [0, 90, -90], + "translation": [0, 0, -8] + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/create/textures/gui/curiosities2.png b/src/main/resources/assets/create/textures/gui/curiosities2.png new file mode 100644 index 0000000000000000000000000000000000000000..26fce588cc9c0e159e2d3e60a9024ef4c584931b GIT binary patch literal 1407 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K58911MRQ8&P5D>38$lZxy-8q?;Kn_c~qpu?a z!^VE@KZ&eBen@~%h%1n0Wo2bzVq#-s`*bjuk&$u#ESGRihBzZe78aHX6DCwtRP5NX z!@}G~Tg%}8|Nq_H-R9=z$BrEf4Gm38OMCR_QAtV3jT<*_+_-W5`t>DCmH-X(?)&i< zNXe80`2_>D-~tTdn;u;Us^cv1h%9Dc;5!7ujG`J|4M4Z{c)B=-RK&fV-B@(XK)~gy zn#inWjSRjDfBx5p9m}4Ox*@wb=;_Vcd5I4nxm-Hkwr%Fh;`?{XpU?Z#-0u=;pFi*F z^$*Xt#o7IwzFfrOyN$Taww&&08~gt=m`^WdNjSaDqk#p85;`|cWZ;~@kaKg|tM!K> z7UfJk%?eZ~z9CB2R@;A7j_qpsk5vkXr>~Uya5>(T`@jA=6-is}xbM#&t*pDG0#s?e zb9(&EiiDNZO`fl3+4HaNbm?BU^X_r$Iaym?FWD3yfT}r^%bHE`^K{qG zNrlX}yiMm%T+R4A^e^+i-saEC^vvIXm*;sN$b2ilC}ZAw#;=Dh|0mw#*irdEfcaJX zuW9dWa@_W@g*^Q%`sU55SDW*H_x{}bd-vxRjBlfNeU5T4K7Y00RPEM<72#L63*XQ2 zx7c6)e{JQLI_Z0t=Ki10_Jj5O%{?3DxbtS*H!?YYu|aR!=LL*2+P|FNZ1TYN*nZ*Y zbIoiIn8VHfezxJQ_-0_^?BZ89nzc-d}k%&jg5v`4N?o(RxqBG zN-j5jC~`vc-4%v6HzZ6QcmtTPG^F)z+&!y+>xoEt7DHK1kCcE(!sfn>bJ=-c+`D9d z{z`+yU$+xw>%KGm)m*@)uzW`_^M>SPV6cNU&oVvs4xcqfCI?=b+kb!N$o%f_v*-70 z{FyJsi(h}dUWV7B-u6Kh&;*28he|KSrJ6PT*?;~#N6t;L=O4=7eezUKi00ZoZ|$4! zLJhjNl^BHr<}}zF%3q!0dBDA8^|If8(}kEf3vT%P$7YFvfjr~w!-}nqlAIpN3rZOO z>3&dB=xjX18dA>|!FqTEc`dE;cnh> z#RZieEHmcszar0A|Ks#eX2x&N^}pFFSo{xlX!<<;w_1hme^-aD&(pOP7?>u_sdr<# zG^gHd2g|v;pD$Rz`}~b)78&qol`;+ E0C|39xc~qF literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/create/textures/item/linked_controller.png b/src/main/resources/assets/create/textures/item/linked_controller.png new file mode 100644 index 0000000000000000000000000000000000000000..474b3bf2c1cd3547b1d4f2fac136655b40585339 GIT binary patch literal 351 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJV{wqX6T`Z5GB1G~mUKs7M+SzC z{oH>NS%G|~0G|-oBh$T275NS1_?)yw*0tEpC^Kma(MWYxw`F9oQW5kwlJL|Qx6>2~ zwvY;AWb|fa?2OeZ^3iV1@~KO7&keH&8dGtjc|DL4D+%%o{*MhXFkU+F1gL_uz$3Dl zfr0NZ2s0kfUy%Y7Z1Hq)4ABVA?PcUUtia(KxJpbUc6Z_b)$g)rrN(|c(z543dxz7U z{>R&LHLZ_ISe)S!6j>g-#cbU%-=+LMJS(S)UiGPJe~}cmb>qrYGlXMrtdf!r`z9+H zzp$fKAxf?0+_D}?8J>?5C+`l{JHBK}(G(ljf4m)^E5CAgT(A7vU9VkU*YaEXT{zD& TfzR%s5M%Ik^>bP0l+XkKkgS3_ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/create/textures/item/linked_controller_powered.png b/src/main/resources/assets/create/textures/item/linked_controller_powered.png new file mode 100644 index 0000000000000000000000000000000000000000..bf0dcb3d3bba9d786edeb51edb7bebc7ce5aff7d GIT binary patch literal 350 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJV{wqX6T`Z5GB1G~mUKs7M+SzC z{oH>NS%G|~0G|-oBh$T275NS1_?)yw*0tEpC^Kma(MWYxpU%Kwr6TBWB;lzqZl@^} zY$0`)fnf^+Luaf`k&pKN?dvwJSTJK^7tomXPm=q9lvqiSU+{lyfPwMSfhRx}oCO|{ z#S9F5hd`K7RKu$QDA?@j;uxY4oZHLI$E?V~8u({XMtStR`m1(lm%TKTHB=O?5SaM+ z^+tZhBPmbzCT~AgIic5U>b0GkRtF%}28J29*~C-ZWmqHw)*fKQ0))q5xY|Npo9$fE!M zzrFo>bJ5D4ufHB1J+~dG`o-C;l|YKKB*-uLKNK(o`&S5o1PeSOiy0XB4ude`@%$Aj zK*4xV7sn8d;L>y4Tn7v|m@i1oef!tnre1pS28WfE0h-??)*tYxWfYjXaaD+gK&ac- zsSIxYJt{YpGj_;)Z984$*mP8?NLN1K`+Qs1M>gTe~DWM4fJ2zo8 delta 226 zcmV<803H8^0`dWn7=Hu<0002(-QrRJ000DMK}|sb0I`n?{9y$E001FSOjJbx003=q zU+wkT#m={Xg=zKr;i9RGyTqc^-pK#|_W%F>w1D3n00001bW%=J06^y0W&i*HZ%IT! zR0!8&U_b_|AQacCjs;+PMaQZt5MxExs#VK@LR?)dXRQJWaa&c*oH+|5#8tF%=FC-% z6BxKsyJoH`Rs=CLR+SrvOkm*53|(H_I%NU_!?dX@TEjAd=5S^%a><+kGI3hUOfb#B cITOVN0Q8S0kPivr+5i9m07*qoM6N<$f+!?hr2qf`