Redstone gamepads

- Added the Linked Controller
This commit is contained in:
simibubi 2021-05-26 22:03:06 +02:00
parent ffa252ac25
commit 09691b4b40
55 changed files with 1649 additions and 96 deletions

View file

@ -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

View file

@ -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",

View file

@ -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",

View file

@ -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",

View file

@ -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",

View file

@ -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",

View file

@ -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",

View file

@ -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",

View file

@ -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": "ターゲットが見つかりません",

View file

@ -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": "목표 없음",

View file

@ -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",

View file

@ -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",

View file

@ -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",

View file

@ -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": "Нет целей",

View file

@ -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": "没有目标",

View file

@ -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": "沒有目標",

View file

@ -0,0 +1,3 @@
{
"parent": "create:item/linked_controller/item"
}

View file

@ -28,8 +28,8 @@
"trigger": "create:bracket_apply",
"conditions": {
"accepted_entries": [
"create:large_cogwheel",
"create:cogwheel"
"create:cogwheel",
"create:large_cogwheel"
]
}
},

View file

@ -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;
@ -36,6 +38,9 @@ public class AllContainerTypes {
public static final ContainerEntry<AttributeFilterContainer> ATTRIBUTE_FILTER =
register("attribute_filter", AttributeFilterContainer::new, () -> AttributeFilterScreen::new);
public static final ContainerEntry<LinkedControllerContainer> LINKED_CONTROLLER =
register("linked_controller", LinkedControllerContainer::new, () -> LinkedControllerScreen::new);
private static <C extends Container, S extends Screen & IHasContainer<C>> ContainerEntry<C> register(String name, ForgeContainerFactory<C> factory, NonNullSupplier<ScreenFactory<C, S>> screenFactory) {
return Create.registrate().container(name, factory, screenFactory).register();
}

View file

@ -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;
@ -228,6 +230,12 @@ public class AllItems {
.model(AssetLookup.itemModelWithPartials())
.register();
public static final ItemEntry<LinkedControllerItem> LINKED_CONTROLLER =
REGISTRATE.item("linked_controller", LinkedControllerItem::new)
.transform(CreateRegistrate.customRenderedItem(() -> LinkedControllerModel::new))
.model(AssetLookup.itemModelWithPartials())
.register();
public static final ItemEntry<MinecartContraptionItem> MINECART_CONTRAPTION =
REGISTRATE.item("minecart_contraption", MinecartContraptionItem::rideable)
.register();

View file

@ -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_);
}

View file

@ -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<Frequency, Frequency> getNetworkKey();
public BlockPos getLocation();
}

View file

@ -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<IWorld, Map<Pair<Frequency, Frequency>, Set<LinkBehaviour>>> connections = new IdentityHashMap<>();
static final Map<IWorld, Map<Pair<Frequency, Frequency>, Set<IRedstoneLinkable>>> 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<LinkBehaviour> getNetworkOf(LinkBehaviour actor) {
Map<Pair<Frequency, Frequency>, Set<LinkBehaviour>> networksInWorld = networksIn(actor.getWorld());
public Set<IRedstoneLinkable> getNetworkOf(IWorld world, IRedstoneLinkable actor) {
Map<Pair<Frequency, Frequency>, Set<IRedstoneLinkable>> networksInWorld = networksIn(world);
Pair<Frequency, Frequency> 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<LinkBehaviour> network = getNetworkOf(actor);
public void removeFromNetwork(IWorld world, IRedstoneLinkable actor) {
Set<IRedstoneLinkable> 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<LinkBehaviour> network = getNetworkOf(actor);
public void updateNetworkOf(IWorld world, IRedstoneLinkable actor) {
Set<IRedstoneLinkable> network = getNetworkOf(world, actor);
int power = 0;
for (Iterator<LinkBehaviour> iterator = network.iterator(); iterator.hasNext();) {
LinkBehaviour other = iterator.next();
if (other.tileEntity.isRemoved()) {
for (Iterator<IRedstoneLinkable> 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<Pair<Frequency, Frequency>, Set<LinkBehaviour>> networksIn(IWorld world) {
public Map<Pair<Frequency, Frequency>, Set<IRedstoneLinkable>> 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);

View file

@ -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<Frequency, Frequency> 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());
}
}

View file

@ -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<Integer> currentlyPressed = new HashSet<>();
private static BlockPos selectedLocation = BlockPos.ZERO;
private static Vector<KeyBinding> controls;
private static int packetCooldown;
public static Vector<KeyBinding> 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<KeyBinding> controls = getControls();
Collection<Integer> pressedKeys = new HashSet<>();
for (int i = 0; i < controls.size(); i++) {
if (isActuallyPressed(controls.get(i)))
pressedKeys.add(i);
}
Collection<Integer> newKeys = new HashSet<>(pressedKeys);
Collection<Integer> 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<KeyBinding> controls = getControls();
for (int i = 0; i < controls.size(); i++) {
KeyBinding keyBinding = controls.get(i);
keys[i] = keyBinding.getBoundKeyLocalizedText()
.getString();
}
List<ITextComponent> 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();
}
}

View file

@ -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);
}
}

View file

@ -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<Integer> activatedButtons;
private boolean press;
public LinkedControllerInputPacket(Collection<Integer> 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);
}
}

View file

@ -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<ItemStack> 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<RedstoneLinkNetworkHandler.Frequency> 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());
}
}

View file

@ -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<LinkedControllerModel> {
static LerpedFloat equipProgress;
static Vector<LerpedFloat> 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();
}
}

View file

@ -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();
}
}

View file

@ -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) {
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);
}

View file

@ -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<LinkedControllerContainer> {
protected AllGuiTextures background;
private List<Rectangle2d> 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<ITextComponent> getTooltipFromItem(ItemStack stack) {
List<ITextComponent> list = super.getTooltipFromItem(stack);
return hoveredSlot != null ? addToTooltip(list, hoveredSlot.getSlotIndex()) : list;
}
private List<ITextComponent> addToTooltip(List<ITextComponent> 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).<GuiGameElement
.GuiRenderBuilder>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<Rectangle2d> getExtraAreas() {
return extraAreas;
}
}

View file

@ -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<Map<UUID, Collection<ManualFrequencyEntry>>> receivedInputs =
new WorldAttached<>(HashMap::new);
static final int TIMEOUT = 30;
public static void tick(IWorld world) {
Map<UUID, Collection<ManualFrequencyEntry>> map = receivedInputs.get(world);
for (Iterator<Entry<UUID, Collection<ManualFrequencyEntry>>> iterator = map.entrySet()
.iterator(); iterator.hasNext();) {
Entry<UUID, Collection<ManualFrequencyEntry>> entry = iterator.next();
Collection<ManualFrequencyEntry> list = entry.getValue();
for (Iterator<ManualFrequencyEntry> 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<Couple<Frequency>> collect,
boolean pressed) {
Map<UUID, Collection<ManualFrequencyEntry>> map = receivedInputs.get(world);
Collection<ManualFrequencyEntry> list = map.computeIfAbsent(uniqueID, $ -> new ArrayList<>());
WithNext: for (Couple<Frequency> activated : collect) {
for (Iterator<ManualFrequencyEntry> 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<Couple<Frequency>> implements IRedstoneLinkable {
private BlockPos pos;
public ManualFrequencyEntry(BlockPos pos, Couple<Frequency> 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<Frequency, Frequency> getNetworkKey() {
return Pair.of(getSecond().getFirst(), getSecond().getSecond());
}
}
}

View file

@ -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);
}

View file

@ -30,7 +30,7 @@ import net.minecraft.util.text.ITextComponent;
public abstract class AbstractFilterScreen<F extends AbstractFilterContainer> extends AbstractSimiContainerScreen<F> {
protected AllGuiTextures background;
private List<Rectangle2d> extraAreas = Collections.EMPTY_LIST;
private List<Rectangle2d> extraAreas = Collections.emptyList();
private IconButton resetButton;
private IconButton confirmButton;
@ -146,7 +146,7 @@ public abstract class AbstractFilterScreen<F extends AbstractFilterContainer> ex
if (resetButton.isHovered()) {
container.clearContents();
contentsCleared();
sendOptionUpdate(Option.CLEAR);
container.sendClearPacket();
return true;
}
}

View file

@ -48,7 +48,7 @@ public class AttributeFilterContainer extends AbstractFilterContainer {
}
@Override
protected void clearContents() {
public void clearContents() {
selectedAttributes.clear();
}

View file

@ -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)

View file

@ -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,10 +102,12 @@ public class ClientEvents {
return;
if (event.phase == Phase.START) {
LinkedControllerClientHandler.tick();
AirCurrent.tickClientPlayerSounds();
return;
}
SoundScapes.tick();
AnimationTickHolder.tick();
FastRenderDispatcher.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

View file

@ -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

View file

@ -58,6 +58,8 @@ public enum AllGuiTextures implements IScreenRenderable {
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),
JEI_CHANCE_SLOT("jei/widgets.png", 20, 156, 18, 18),

View file

@ -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) {
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);
}
}

View file

@ -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();
}

View file

@ -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

View file

@ -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));

View file

@ -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;

View file

@ -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<LinkBehaviour> 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<Frequency, Frequency> 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();
}
}

View file

@ -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));
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);

View file

@ -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",

View file

@ -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"}
}
}
]
}

View file

@ -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]
}
}
}

View file

@ -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]
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 351 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 350 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 242 B

After

Width:  |  Height:  |  Size: 262 B