Click to Craft

- Added Crafting Blueprints
- Bit of "Ghost-item" Container refactoring
This commit is contained in:
simibubi 2021-06-03 01:03:43 +02:00
parent 8fe3901c98
commit 032fa90ec6
55 changed files with 2122 additions and 200 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
e9c463e0cf56ed28ee26a33debeae3ecc2e941d2 assets/create/lang/en_ud.json
dceb2a935135d2ef502cdcba7c9d58f64062513f assets/create/lang/en_us.json
eb40acb99f3c7af50b840f3c2058d7a7bdd5cff7 assets/create/lang/unfinished/de_de.json
bcbfd3a6768daf265a1c01a424e985a3fdec6504 assets/create/lang/unfinished/es_es.json
50dec8a7eb983ac4d29f3eeba3273dbaeca26902 assets/create/lang/unfinished/es_mx.json
cc723673107651024f3fc0e43690ac467ff729b2 assets/create/lang/unfinished/fr_fr.json
99452bacb5d80715ea0a52106b7e2734a32c55d4 assets/create/lang/unfinished/it_it.json
f3058ea623666a43029af307f632197c8ff8dcab assets/create/lang/unfinished/ja_jp.json
d756b02573d6a3a3b73bd03ec69fe760825e1606 assets/create/lang/unfinished/ko_kr.json
281712735ab6437a417dde63c855e18eb19493a0 assets/create/lang/unfinished/nl_nl.json
24056aefb7ff79a2127c194fe2918ab9e745d6b5 assets/create/lang/unfinished/pl_pl.json
0f9c83a9f70d809d8f66c0438529b169b92ffdb1 assets/create/lang/unfinished/pt_br.json
ff35273842d3190aa361f2a8ca7edae80f97864d assets/create/lang/unfinished/ru_ru.json
139a31cfd09d4aaca33d118d28de735ba72f4f0d assets/create/lang/unfinished/zh_cn.json
19bfa8f57e8b395a2cfd98039f44301a61c1f73c assets/create/lang/unfinished/zh_tw.json
c71f5246d2cb8e9913d1552d23fcc82c43cde7a0 assets/create/lang/en_ud.json
16738c5e5eeba8be9808ea44b695a76cd665156d assets/create/lang/en_us.json
ffe020d59e813db401690b6c225b47a6e40c5c0b assets/create/lang/unfinished/de_de.json
37bd77cae941d650e641079ce826894a9d738a15 assets/create/lang/unfinished/es_es.json
5dc0552006fc2ca19bd12801bdfd9ebd34ce9ff1 assets/create/lang/unfinished/es_mx.json
ad91c2c41ec0cbfab9341256f2e9bf5cf08b8cdc assets/create/lang/unfinished/fr_fr.json
effbb185a45057ca686bdd5ef96f722f1c17bf4f assets/create/lang/unfinished/it_it.json
e7a925d5187e3ca3cc417356012bfc68e08e262c assets/create/lang/unfinished/ja_jp.json
3fcd98c23d179b63f48fff65806686f36170c09c assets/create/lang/unfinished/ko_kr.json
04852300087f939dba6cd6941af3e0a35c710dfa assets/create/lang/unfinished/nl_nl.json
b839c1dae703adaf5de99f3f40f3444f363752d9 assets/create/lang/unfinished/pl_pl.json
2a514e604fb6e75ba79670576f2eb1d976be4416 assets/create/lang/unfinished/pt_br.json
67c0bd43defecbc059a0afd89dae55d99198c95e assets/create/lang/unfinished/ru_ru.json
1f5da639f8450d8cd818d938a871fad9a1041b3a assets/create/lang/unfinished/zh_cn.json
25bf9dbb6163fb4be36afa0d4917bedbecb1cd3b 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
@ -1273,6 +1273,7 @@ d7cb2f7bac8fae893fc5179af8140786a908f3f5 assets/create/models/item/copper_shingl
f56bf22324faf8958eaef4d94b958f1108d52e5a assets/create/models/item/copper_tiles.json
5583368909c319acfcf0f7a419bedf23272fe613 assets/create/models/item/copper_valve_handle.json
4e253e7c0626dfd76e2d39786ce1a34e0baaa62d assets/create/models/item/crafter_slot_cover.json
1f947dafff30da701b7675f5b026ccab3129b079 assets/create/models/item/crafting_blueprint.json
7b333dea353afaa27b182aedc647c9e9e34e92ef assets/create/models/item/creative_crate.json
f7d06c52c3ca8c22ad67f5741471f06ac22e7fcb assets/create/models/item/creative_fluid_tank.json
5b39403f6c81f05e566b621b62e267267de47c41 assets/create/models/item/creative_motor.json
@ -1653,7 +1654,7 @@ d080b1b25e5bc8baf5aee68691b08c7f12ece3b0 assets/create/models/item/windmill_bear
a80fb25a0b655e76be986b5b49fcb0f03461a1ab assets/create/models/item/zinc_nugget.json
b1689617190c05ef34bd18456b0c7ae09bb3210f assets/create/models/item/zinc_ore.json
6490fa0587db770cf7c794b47f3bcd2b691f4226 assets/create/sounds.json
0f1b4b980afba9bf2caf583b88e261bba8b10313 data/create/advancements/aesthetics.json
5d0cc4c0255dc241e61c173b31ddca70c88d08e4 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

@ -409,6 +409,7 @@
"block.create.zinc_block": "\u0254u\u0131Z \u025Fo \u029E\u0254o\u05DF\u15FA",
"block.create.zinc_ore": "\u01DD\u0279O \u0254u\u0131Z",
"entity.create.contraption": "uo\u0131\u0287d\u0250\u0279\u0287uo\u0186",
"entity.create.crafting_blueprint": "\u0287u\u0131\u0279d\u01DDn\u05DF\u15FA bu\u0131\u0287\u025F\u0250\u0279\u0186",
"entity.create.gantry_contraption": "uo\u0131\u0287d\u0250\u0279\u0287uo\u0186 \u028E\u0279\u0287u\u0250\u2141",
"entity.create.seat": "\u0287\u0250\u01DDS",
"entity.create.stationary_contraption": "uo\u0131\u0287d\u0250\u0279\u0287uo\u0186 \u028E\u0279\u0250uo\u0131\u0287\u0250\u0287S",
@ -437,6 +438,7 @@
"item.create.copper_nugget": "\u0287\u01DDbbnN \u0279\u01DDddo\u0186",
"item.create.copper_sheet": "\u0287\u01DD\u01DD\u0265S \u0279\u01DDddo\u0186",
"item.create.crafter_slot_cover": "\u0279\u01DD\u028Co\u0186 \u0287o\u05DFS \u0279\u01DD\u0287\u025F\u0250\u0279\u0186",
"item.create.crafting_blueprint": "\u0287u\u0131\u0279d\u01DDn\u05DF\u15FA bu\u0131\u0287\u025F\u0250\u0279\u0186",
"item.create.crushed_aluminum_ore": "\u01DD\u0279O \u026Fnu\u0131\u026Fn\u05DF\u2C6F p\u01DD\u0265sn\u0279\u0186",
"item.create.crushed_brass": "ss\u0250\u0279\u15FA p\u01DD\u0265sn\u0279\u0186",
"item.create.crushed_copper_ore": "\u01DD\u0279O \u0279\u01DDddo\u0186 p\u01DD\u0265sn\u0279\u0186",

View file

@ -413,6 +413,7 @@
"block.create.zinc_ore": "Zinc Ore",
"entity.create.contraption": "Contraption",
"entity.create.crafting_blueprint": "Crafting Blueprint",
"entity.create.gantry_contraption": "Gantry Contraption",
"entity.create.seat": "Seat",
"entity.create.stationary_contraption": "Stationary Contraption",
@ -443,6 +444,7 @@
"item.create.copper_nugget": "Copper Nugget",
"item.create.copper_sheet": "Copper Sheet",
"item.create.crafter_slot_cover": "Crafter Slot Cover",
"item.create.crafting_blueprint": "Crafting Blueprint",
"item.create.crushed_aluminum_ore": "Crushed Aluminum Ore",
"item.create.crushed_brass": "Crushed Brass",
"item.create.crushed_copper_ore": "Crushed Copper Ore",
@ -1111,6 +1113,14 @@
"create.linked_controller.frequency_slot_1": "Keybind: %1$s, Freq. #1",
"create.linked_controller.frequency_slot_2": "Keybind: %1$s, Freq. #2",
"create.crafting_blueprint.crafting_slot": "Ingredient Slot",
"create.crafting_blueprint.filter_items_viable": "Advanced filter items are viable",
"create.crafting_blueprint.display_slot": "Display Slot",
"create.crafting_blueprint.inferred": "Inferred from recipe",
"create.crafting_blueprint.manually_assigned": "Manually assigned",
"create.crafting_blueprint.secondary_display_slot": "Secondary Display Slot",
"create.crafting_blueprint.optional": "Optional",
"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: 953",
"_": "Missing Localizations: 962",
"_": "->------------------------] Game Elements [------------------------<-",
@ -414,6 +414,7 @@
"block.create.zinc_ore": "Zinkerz",
"entity.create.contraption": "Vorrichtung",
"entity.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint",
"entity.create.gantry_contraption": "Portalkran Vorrichtung",
"entity.create.seat": "Sitz",
"entity.create.stationary_contraption": "Stationäre Vorrichtung",
@ -444,6 +445,7 @@
"item.create.copper_nugget": "Kupferklumpen",
"item.create.copper_sheet": "Kupferblech",
"item.create.crafter_slot_cover": "Handwerkseinheit Slot Abdeckung",
"item.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint",
"item.create.crushed_aluminum_ore": "Zerkleinertes Aluminiumerz",
"item.create.crushed_brass": "Zerkleinertes Messing",
"item.create.crushed_copper_ore": "Zerkleinertes Kupfererz",
@ -1112,6 +1114,14 @@
"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.crafting_blueprint.crafting_slot": "UNLOCALIZED: Ingredient Slot",
"create.crafting_blueprint.filter_items_viable": "UNLOCALIZED: Advanced filter items are viable",
"create.crafting_blueprint.display_slot": "UNLOCALIZED: Display Slot",
"create.crafting_blueprint.inferred": "UNLOCALIZED: Inferred from recipe",
"create.crafting_blueprint.manually_assigned": "UNLOCALIZED: Manually assigned",
"create.crafting_blueprint.secondary_display_slot": "UNLOCALIZED: Secondary Display Slot",
"create.crafting_blueprint.optional": "UNLOCALIZED: Optional",
"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: 654",
"_": "Missing Localizations: 663",
"_": "->------------------------] Game Elements [------------------------<-",
@ -414,6 +414,7 @@
"block.create.zinc_ore": "Mineral de zinc",
"entity.create.contraption": "Artilugio",
"entity.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint",
"entity.create.gantry_contraption": "Artilugio de grúa",
"entity.create.seat": "Asiento",
"entity.create.stationary_contraption": "Artilugio estacionario",
@ -444,6 +445,7 @@
"item.create.copper_nugget": "Pepita de cobre",
"item.create.copper_sheet": "Lámina de cobre",
"item.create.crafter_slot_cover": "Tapa de ranura del Autoensamblador mecánico",
"item.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint",
"item.create.crushed_aluminum_ore": "Mineral de aluminio molido",
"item.create.crushed_brass": "Latón molido",
"item.create.crushed_copper_ore": "Mineral de cobre molido",
@ -1112,6 +1114,14 @@
"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.crafting_blueprint.crafting_slot": "UNLOCALIZED: Ingredient Slot",
"create.crafting_blueprint.filter_items_viable": "UNLOCALIZED: Advanced filter items are viable",
"create.crafting_blueprint.display_slot": "UNLOCALIZED: Display Slot",
"create.crafting_blueprint.inferred": "UNLOCALIZED: Inferred from recipe",
"create.crafting_blueprint.manually_assigned": "UNLOCALIZED: Manually assigned",
"create.crafting_blueprint.secondary_display_slot": "UNLOCALIZED: Secondary Display Slot",
"create.crafting_blueprint.optional": "UNLOCALIZED: Optional",
"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: 1277",
"_": "Missing Localizations: 1286",
"_": "->------------------------] Game Elements [------------------------<-",
@ -414,6 +414,7 @@
"block.create.zinc_ore": "Mineral de Zinc",
"entity.create.contraption": "Artefacto",
"entity.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint",
"entity.create.gantry_contraption": "UNLOCALIZED: Gantry Contraption",
"entity.create.seat": "Asiento",
"entity.create.stationary_contraption": "Artefacto Estacionario",
@ -444,6 +445,7 @@
"item.create.copper_nugget": "Pepita de Cobre",
"item.create.copper_sheet": "Lámina de Cobre",
"item.create.crafter_slot_cover": "Cubierta de Ranura del Crafter",
"item.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint",
"item.create.crushed_aluminum_ore": "Mineral de Aluminio Molido",
"item.create.crushed_brass": "Latón Molido",
"item.create.crushed_copper_ore": "Mineral de Cobre Molido",
@ -1112,6 +1114,14 @@
"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.crafting_blueprint.crafting_slot": "UNLOCALIZED: Ingredient Slot",
"create.crafting_blueprint.filter_items_viable": "UNLOCALIZED: Advanced filter items are viable",
"create.crafting_blueprint.display_slot": "UNLOCALIZED: Display Slot",
"create.crafting_blueprint.inferred": "UNLOCALIZED: Inferred from recipe",
"create.crafting_blueprint.manually_assigned": "UNLOCALIZED: Manually assigned",
"create.crafting_blueprint.secondary_display_slot": "UNLOCALIZED: Secondary Display Slot",
"create.crafting_blueprint.optional": "UNLOCALIZED: Optional",
"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: 1205",
"_": "Missing Localizations: 1214",
"_": "->------------------------] Game Elements [------------------------<-",
@ -414,6 +414,7 @@
"block.create.zinc_ore": "Minerai de zinc",
"entity.create.contraption": "Engin",
"entity.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint",
"entity.create.gantry_contraption": "UNLOCALIZED: Gantry Contraption",
"entity.create.seat": "Siège",
"entity.create.stationary_contraption": "Engin stationnaire",
@ -444,6 +445,7 @@
"item.create.copper_nugget": "Pépite de cuivre",
"item.create.copper_sheet": "Plaques de cuivre",
"item.create.crafter_slot_cover": "Couvercle",
"item.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint",
"item.create.crushed_aluminum_ore": "Aluminium concassé",
"item.create.crushed_brass": "Laiton concassé",
"item.create.crushed_copper_ore": "Cuivre concassé",
@ -1112,6 +1114,14 @@
"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.crafting_blueprint.crafting_slot": "UNLOCALIZED: Ingredient Slot",
"create.crafting_blueprint.filter_items_viable": "UNLOCALIZED: Advanced filter items are viable",
"create.crafting_blueprint.display_slot": "UNLOCALIZED: Display Slot",
"create.crafting_blueprint.inferred": "UNLOCALIZED: Inferred from recipe",
"create.crafting_blueprint.manually_assigned": "UNLOCALIZED: Manually assigned",
"create.crafting_blueprint.secondary_display_slot": "UNLOCALIZED: Secondary Display Slot",
"create.crafting_blueprint.optional": "UNLOCALIZED: Optional",
"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: 671",
"_": "Missing Localizations: 680",
"_": "->------------------------] Game Elements [------------------------<-",
@ -414,6 +414,7 @@
"block.create.zinc_ore": "Zinco grezzo",
"entity.create.contraption": "Contrazione",
"entity.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint",
"entity.create.gantry_contraption": "UNLOCALIZED: Gantry Contraption",
"entity.create.seat": "Sedile",
"entity.create.stationary_contraption": "Contrazione stazionaria",
@ -444,6 +445,7 @@
"item.create.copper_nugget": "Pepita di rame",
"item.create.copper_sheet": "Lamiera di rame",
"item.create.crafter_slot_cover": "Rivestimento per slot da costruzione",
"item.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint",
"item.create.crushed_aluminum_ore": "Alluminio grezzo frantumato",
"item.create.crushed_brass": "Ottone frantumato",
"item.create.crushed_copper_ore": "Rame grezzo frantumato",
@ -1112,6 +1114,14 @@
"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.crafting_blueprint.crafting_slot": "UNLOCALIZED: Ingredient Slot",
"create.crafting_blueprint.filter_items_viable": "UNLOCALIZED: Advanced filter items are viable",
"create.crafting_blueprint.display_slot": "UNLOCALIZED: Display Slot",
"create.crafting_blueprint.inferred": "UNLOCALIZED: Inferred from recipe",
"create.crafting_blueprint.manually_assigned": "UNLOCALIZED: Manually assigned",
"create.crafting_blueprint.secondary_display_slot": "UNLOCALIZED: Secondary Display Slot",
"create.crafting_blueprint.optional": "UNLOCALIZED: Optional",
"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: 35",
"_": "Missing Localizations: 44",
"_": "->------------------------] Game Elements [------------------------<-",
@ -414,6 +414,7 @@
"block.create.zinc_ore": "亜鉛鉱石",
"entity.create.contraption": "からくり",
"entity.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint",
"entity.create.gantry_contraption": "ガントリーからくり",
"entity.create.seat": "シート",
"entity.create.stationary_contraption": "付設からくり",
@ -444,6 +445,7 @@
"item.create.copper_nugget": "銅塊",
"item.create.copper_sheet": "銅板",
"item.create.crafter_slot_cover": "クラフタースロットカバー",
"item.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint",
"item.create.crushed_aluminum_ore": "砕いたアルミニウム鉱石",
"item.create.crushed_brass": "砕いた真鍮",
"item.create.crushed_copper_ore": "砕いた銅鉱石",
@ -1112,6 +1114,14 @@
"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.crafting_blueprint.crafting_slot": "UNLOCALIZED: Ingredient Slot",
"create.crafting_blueprint.filter_items_viable": "UNLOCALIZED: Advanced filter items are viable",
"create.crafting_blueprint.display_slot": "UNLOCALIZED: Display Slot",
"create.crafting_blueprint.inferred": "UNLOCALIZED: Inferred from recipe",
"create.crafting_blueprint.manually_assigned": "UNLOCALIZED: Manually assigned",
"create.crafting_blueprint.secondary_display_slot": "UNLOCALIZED: Secondary Display Slot",
"create.crafting_blueprint.optional": "UNLOCALIZED: Optional",
"create.hint.hose_pulley.title": "底なし搬出",
"create.hint.hose_pulley": "対象となる液体は無限とみなされています。",
"create.hint.mechanical_arm_no_targets.title": "ターゲットが見つかりません",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 724",
"_": "Missing Localizations: 733",
"_": "->------------------------] Game Elements [------------------------<-",
@ -414,6 +414,7 @@
"block.create.zinc_ore": "아연 광석",
"entity.create.contraption": "장치",
"entity.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint",
"entity.create.gantry_contraption": "UNLOCALIZED: Gantry Contraption",
"entity.create.seat": "좌석",
"entity.create.stationary_contraption": "고정된 장치",
@ -444,6 +445,7 @@
"item.create.copper_nugget": "구리 조각",
"item.create.copper_sheet": "구리 판",
"item.create.crafter_slot_cover": "조합기 슬롯 덮개",
"item.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint",
"item.create.crushed_aluminum_ore": "UNLOCALIZED: Crushed Aluminum Ore",
"item.create.crushed_brass": "분쇄된 황동",
"item.create.crushed_copper_ore": "분쇄된 구리 광석",
@ -1112,6 +1114,14 @@
"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.crafting_blueprint.crafting_slot": "UNLOCALIZED: Ingredient Slot",
"create.crafting_blueprint.filter_items_viable": "UNLOCALIZED: Advanced filter items are viable",
"create.crafting_blueprint.display_slot": "UNLOCALIZED: Display Slot",
"create.crafting_blueprint.inferred": "UNLOCALIZED: Inferred from recipe",
"create.crafting_blueprint.manually_assigned": "UNLOCALIZED: Manually assigned",
"create.crafting_blueprint.secondary_display_slot": "UNLOCALIZED: Secondary Display Slot",
"create.crafting_blueprint.optional": "UNLOCALIZED: Optional",
"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: 1588",
"_": "Missing Localizations: 1597",
"_": "->------------------------] Game Elements [------------------------<-",
@ -414,6 +414,7 @@
"block.create.zinc_ore": "UNLOCALIZED: Zinc Ore",
"entity.create.contraption": "UNLOCALIZED: Contraption",
"entity.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint",
"entity.create.gantry_contraption": "UNLOCALIZED: Gantry Contraption",
"entity.create.seat": "UNLOCALIZED: Seat",
"entity.create.stationary_contraption": "UNLOCALIZED: Stationary Contraption",
@ -444,6 +445,7 @@
"item.create.copper_nugget": "Koper klompje",
"item.create.copper_sheet": "UNLOCALIZED: Copper Sheet",
"item.create.crafter_slot_cover": "UNLOCALIZED: Crafter Slot Cover",
"item.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint",
"item.create.crushed_aluminum_ore": "UNLOCALIZED: Crushed Aluminum Ore",
"item.create.crushed_brass": "Gemalen Brons",
"item.create.crushed_copper_ore": "UNLOCALIZED: Crushed Copper Ore",
@ -1112,6 +1114,14 @@
"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.crafting_blueprint.crafting_slot": "UNLOCALIZED: Ingredient Slot",
"create.crafting_blueprint.filter_items_viable": "UNLOCALIZED: Advanced filter items are viable",
"create.crafting_blueprint.display_slot": "UNLOCALIZED: Display Slot",
"create.crafting_blueprint.inferred": "UNLOCALIZED: Inferred from recipe",
"create.crafting_blueprint.manually_assigned": "UNLOCALIZED: Manually assigned",
"create.crafting_blueprint.secondary_display_slot": "UNLOCALIZED: Secondary Display Slot",
"create.crafting_blueprint.optional": "UNLOCALIZED: Optional",
"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: 11",
"_": "Missing Localizations: 20",
"_": "->------------------------] Game Elements [------------------------<-",
@ -414,6 +414,7 @@
"block.create.zinc_ore": "Ruda cynku",
"entity.create.contraption": "Maszyna",
"entity.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint",
"entity.create.gantry_contraption": "Maszyna suwnicowa",
"entity.create.seat": "Siedzenie",
"entity.create.stationary_contraption": "Maszyna stacjonarna",
@ -444,6 +445,7 @@
"item.create.copper_nugget": "Bryłka miedzi",
"item.create.copper_sheet": "Arkusz miedzi",
"item.create.crafter_slot_cover": "Przykrywka na slot stołu rzemieślniczego",
"item.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint",
"item.create.crushed_aluminum_ore": "Rozkruszona ruda żelaza",
"item.create.crushed_brass": "Rozkruszony mosiądz",
"item.create.crushed_copper_ore": "Rozkruszona ruda miedzi",
@ -1112,6 +1114,14 @@
"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.crafting_blueprint.crafting_slot": "UNLOCALIZED: Ingredient Slot",
"create.crafting_blueprint.filter_items_viable": "UNLOCALIZED: Advanced filter items are viable",
"create.crafting_blueprint.display_slot": "UNLOCALIZED: Display Slot",
"create.crafting_blueprint.inferred": "UNLOCALIZED: Inferred from recipe",
"create.crafting_blueprint.manually_assigned": "UNLOCALIZED: Manually assigned",
"create.crafting_blueprint.secondary_display_slot": "UNLOCALIZED: Secondary Display Slot",
"create.crafting_blueprint.optional": "UNLOCALIZED: Optional",
"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: 1640",
"_": "Missing Localizations: 1649",
"_": "->------------------------] Game Elements [------------------------<-",
@ -414,6 +414,7 @@
"block.create.zinc_ore": "UNLOCALIZED: Zinc Ore",
"entity.create.contraption": "UNLOCALIZED: Contraption",
"entity.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint",
"entity.create.gantry_contraption": "UNLOCALIZED: Gantry Contraption",
"entity.create.seat": "UNLOCALIZED: Seat",
"entity.create.stationary_contraption": "UNLOCALIZED: Stationary Contraption",
@ -444,6 +445,7 @@
"item.create.copper_nugget": "UNLOCALIZED: Copper Nugget",
"item.create.copper_sheet": "UNLOCALIZED: Copper Sheet",
"item.create.crafter_slot_cover": "UNLOCALIZED: Crafter Slot Cover",
"item.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint",
"item.create.crushed_aluminum_ore": "UNLOCALIZED: Crushed Aluminum Ore",
"item.create.crushed_brass": "UNLOCALIZED: Crushed Brass",
"item.create.crushed_copper_ore": "UNLOCALIZED: Crushed Copper Ore",
@ -1112,6 +1114,14 @@
"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.crafting_blueprint.crafting_slot": "UNLOCALIZED: Ingredient Slot",
"create.crafting_blueprint.filter_items_viable": "UNLOCALIZED: Advanced filter items are viable",
"create.crafting_blueprint.display_slot": "UNLOCALIZED: Display Slot",
"create.crafting_blueprint.inferred": "UNLOCALIZED: Inferred from recipe",
"create.crafting_blueprint.manually_assigned": "UNLOCALIZED: Manually assigned",
"create.crafting_blueprint.secondary_display_slot": "UNLOCALIZED: Secondary Display Slot",
"create.crafting_blueprint.optional": "UNLOCALIZED: Optional",
"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: 568",
"_": "Missing Localizations: 577",
"_": "->------------------------] Game Elements [------------------------<-",
@ -414,6 +414,7 @@
"block.create.zinc_ore": "Цинковая руда",
"entity.create.contraption": "Штуковина",
"entity.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint",
"entity.create.gantry_contraption": "UNLOCALIZED: Gantry Contraption",
"entity.create.seat": "Сиденье",
"entity.create.stationary_contraption": "Стационарная штуковина",
@ -444,6 +445,7 @@
"item.create.copper_nugget": "Кусочек меди",
"item.create.copper_sheet": "Медный лист",
"item.create.crafter_slot_cover": "Крышка на слот крафтера",
"item.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint",
"item.create.crushed_aluminum_ore": "Измельчённая алюминиевая руда",
"item.create.crushed_brass": "Дроблёная латунь",
"item.create.crushed_copper_ore": "Дроблёная медная руда",
@ -1112,6 +1114,14 @@
"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.crafting_blueprint.crafting_slot": "UNLOCALIZED: Ingredient Slot",
"create.crafting_blueprint.filter_items_viable": "UNLOCALIZED: Advanced filter items are viable",
"create.crafting_blueprint.display_slot": "UNLOCALIZED: Display Slot",
"create.crafting_blueprint.inferred": "UNLOCALIZED: Inferred from recipe",
"create.crafting_blueprint.manually_assigned": "UNLOCALIZED: Manually assigned",
"create.crafting_blueprint.secondary_display_slot": "UNLOCALIZED: Secondary Display Slot",
"create.crafting_blueprint.optional": "UNLOCALIZED: Optional",
"create.hint.hose_pulley.title": "Безграничное снабжение",
"create.hint.hose_pulley": "Целевой водный резервуар считается бесконечным.",
"create.hint.mechanical_arm_no_targets.title": "Нет целей",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 54",
"_": "Missing Localizations: 63",
"_": "->------------------------] Game Elements [------------------------<-",
@ -414,6 +414,7 @@
"block.create.zinc_ore": "锌矿石",
"entity.create.contraption": "装置",
"entity.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint",
"entity.create.gantry_contraption": "起重机装置",
"entity.create.seat": "坐垫",
"entity.create.stationary_contraption": "固定装置",
@ -444,6 +445,7 @@
"item.create.copper_nugget": "铜粒",
"item.create.copper_sheet": "铜板",
"item.create.crafter_slot_cover": "合成器盖板",
"item.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint",
"item.create.crushed_aluminum_ore": "粉碎铝矿石",
"item.create.crushed_brass": "粉碎黄铜",
"item.create.crushed_copper_ore": "粉碎铜矿石",
@ -1112,6 +1114,14 @@
"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.crafting_blueprint.crafting_slot": "UNLOCALIZED: Ingredient Slot",
"create.crafting_blueprint.filter_items_viable": "UNLOCALIZED: Advanced filter items are viable",
"create.crafting_blueprint.display_slot": "UNLOCALIZED: Display Slot",
"create.crafting_blueprint.inferred": "UNLOCALIZED: Inferred from recipe",
"create.crafting_blueprint.manually_assigned": "UNLOCALIZED: Manually assigned",
"create.crafting_blueprint.secondary_display_slot": "UNLOCALIZED: Secondary Display Slot",
"create.crafting_blueprint.optional": "UNLOCALIZED: Optional",
"create.hint.hose_pulley.title": "无限供应",
"create.hint.hose_pulley": "目标液体对象被视为无限量的。",
"create.hint.mechanical_arm_no_targets.title": "没有目标",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 47",
"_": "Missing Localizations: 56",
"_": "->------------------------] Game Elements [------------------------<-",
@ -414,6 +414,7 @@
"block.create.zinc_ore": "鋅礦石",
"entity.create.contraption": "結構",
"entity.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint",
"entity.create.gantry_contraption": "門式結構",
"entity.create.seat": "坐墊",
"entity.create.stationary_contraption": "固定結構",
@ -444,6 +445,7 @@
"item.create.copper_nugget": "銅粒",
"item.create.copper_sheet": "銅板",
"item.create.crafter_slot_cover": "合成器蓋板",
"item.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint",
"item.create.crushed_aluminum_ore": "碎狀鋁礦石",
"item.create.crushed_brass": "碎狀黃銅",
"item.create.crushed_copper_ore": "碎狀銅礦石",
@ -1112,6 +1114,14 @@
"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.crafting_blueprint.crafting_slot": "UNLOCALIZED: Ingredient Slot",
"create.crafting_blueprint.filter_items_viable": "UNLOCALIZED: Advanced filter items are viable",
"create.crafting_blueprint.display_slot": "UNLOCALIZED: Display Slot",
"create.crafting_blueprint.inferred": "UNLOCALIZED: Inferred from recipe",
"create.crafting_blueprint.manually_assigned": "UNLOCALIZED: Manually assigned",
"create.crafting_blueprint.secondary_display_slot": "UNLOCALIZED: Secondary Display Slot",
"create.crafting_blueprint.optional": "UNLOCALIZED: Optional",
"create.hint.hose_pulley.title": "無限供應",
"create.hint.hose_pulley": "目標液體為無限供應",
"create.hint.mechanical_arm_no_targets.title": "沒有目標",

View file

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "create:item/crafting_blueprint"
}
}

View file

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

View file

@ -102,6 +102,10 @@ public class AllBlockPartials {
COPPER_BACKTANK_SHAFT = get("copper_backtank/block_shaft_input"),
COPPER_BACKTANK_COGS = get("copper_backtank/block_cogs"),
CRAFTING_BLUEPRINT_1x1 = getEntity("crafting_blueprint_small"),
CRAFTING_BLUEPRINT_2x2 = getEntity("crafting_blueprint_medium"),
CRAFTING_BLUEPRINT_3x3 = getEntity("crafting_blueprint_large"),
COUPLING_ATTACHMENT = getEntity("minecart_coupling/attachment"),
COUPLING_RING = getEntity("minecart_coupling/ring"),
COUPLING_CONNECTOR = getEntity("minecart_coupling/connector")

View file

@ -1,5 +1,7 @@
package com.simibubi.create;
import com.simibubi.create.content.curiosities.tools.BlueprintContainer;
import com.simibubi.create.content.curiosities.tools.BlueprintScreen;
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;
@ -38,6 +40,9 @@ public class AllContainerTypes {
public static final ContainerEntry<AttributeFilterContainer> ATTRIBUTE_FILTER =
register("attribute_filter", AttributeFilterContainer::new, () -> AttributeFilterScreen::new);
public static final ContainerEntry<BlueprintContainer> CRAFTING_BLUEPRINT =
register("crafting_blueprint", BlueprintContainer::new, () -> BlueprintScreen::new);
public static final ContainerEntry<LinkedControllerContainer> LINKED_CONTROLLER =
register("linked_controller", LinkedControllerContainer::new, () -> LinkedControllerScreen::new);

View file

@ -9,6 +9,8 @@ import com.simibubi.create.content.contraptions.components.structureMovement.Ori
import com.simibubi.create.content.contraptions.components.structureMovement.gantry.GantryContraptionEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueRenderer;
import com.simibubi.create.content.curiosities.tools.BlueprintEntity;
import com.simibubi.create.content.curiosities.tools.BlueprintRenderer;
import com.simibubi.create.foundation.utility.Lang;
import com.tterrag.registrate.util.entry.EntityEntry;
import com.tterrag.registrate.util.nullness.NonNullConsumer;
@ -35,6 +37,11 @@ public class AllEntityTypes {
public static final EntityEntry<SuperGlueEntity> SUPER_GLUE =
register("super_glue", SuperGlueEntity::new, () -> SuperGlueRenderer::new,
EntityClassification.MISC, 10, Integer.MAX_VALUE, false, true, SuperGlueEntity::build);
public static final EntityEntry<BlueprintEntity> CRAFTING_BLUEPRINT =
register("crafting_blueprint", BlueprintEntity::new, () -> BlueprintRenderer::new,
EntityClassification.MISC, 10, Integer.MAX_VALUE, false, true, BlueprintEntity::build);
public static final EntityEntry<SeatEntity> SEAT =
register("seat", SeatEntity::new, () -> SeatEntity.Render::new,
EntityClassification.MISC, 0, Integer.MAX_VALUE, false, true, SeatEntity::build);

View file

@ -35,6 +35,7 @@ import com.simibubi.create.content.curiosities.armor.DivingBootsItem;
import com.simibubi.create.content.curiosities.armor.DivingHelmetItem;
import com.simibubi.create.content.curiosities.symmetry.SymmetryWandItem;
import com.simibubi.create.content.curiosities.symmetry.client.SymmetryWandModel;
import com.simibubi.create.content.curiosities.tools.BlueprintItem;
import com.simibubi.create.content.curiosities.tools.ExtendoGripItem;
import com.simibubi.create.content.curiosities.tools.ExtendoGripModel;
import com.simibubi.create.content.curiosities.tools.SandPaperItem;
@ -197,6 +198,10 @@ public class AllItems {
REGISTRATE.item("minecart_coupling", MinecartCouplingItem::new)
.register();
public static final ItemEntry<BlueprintItem> CRAFTING_BLUEPRINT =
REGISTRATE.item("crafting_blueprint", BlueprintItem::new)
.register();
public static final ItemEntry<SandPaperItem> SAND_PAPER = REGISTRATE.item("sand_paper", SandPaperItem::new)
.transform(CreateRegistrate.customRenderedItem(() -> SandPaperModel::new))
.register();
@ -222,7 +227,7 @@ public class AllItems {
.transform(CreateRegistrate.customRenderedItem(() -> LinkedControllerModel::new))
.model(AssetLookup.itemModelWithPartials())
.register();
public static final ItemEntry<SymmetryWandItem> WAND_OF_SYMMETRY =
REGISTRATE.item("wand_of_symmetry", SymmetryWandItem::new)
.transform(CreateRegistrate.customRenderedItem(() -> SymmetryWandModel::new))

View file

@ -0,0 +1,31 @@
package com.simibubi.create.compat.jei;
import com.simibubi.create.content.curiosities.tools.BlueprintAssignCompleteRecipePacket;
import com.simibubi.create.content.curiosities.tools.BlueprintContainer;
import com.simibubi.create.foundation.networking.AllPackets;
import mezz.jei.api.gui.IRecipeLayout;
import mezz.jei.api.recipe.transfer.IRecipeTransferError;
import mezz.jei.api.recipe.transfer.IRecipeTransferHandler;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.crafting.IRecipe;
public class BlueprintTransferHandler implements IRecipeTransferHandler<BlueprintContainer> {
@Override
public Class<BlueprintContainer> getContainerClass() {
return BlueprintContainer.class;
}
@Override
public IRecipeTransferError transferRecipe(BlueprintContainer container, Object recipe, IRecipeLayout recipeLayout,
PlayerEntity player, boolean maxTransfer, boolean doTransfer) {
if (!(recipe instanceof IRecipe))
return null;
IRecipe<?> iRecipe = (IRecipe<?>) recipe;
// Continued server-side in BlueprintItem.assignCompleteRecipe()
AllPackets.channel.sendToServer(new BlueprintAssignCompleteRecipePacket(iRecipe.getId()));
return null;
}
}

View file

@ -39,6 +39,7 @@ import com.simibubi.create.content.contraptions.components.press.MechanicalPress
import com.simibubi.create.content.contraptions.components.saw.SawTileEntity;
import com.simibubi.create.content.contraptions.fluids.recipe.PotionMixingRecipeManager;
import com.simibubi.create.content.contraptions.processing.BasinRecipe;
import com.simibubi.create.content.curiosities.tools.BlueprintScreen;
import com.simibubi.create.content.logistics.block.inventories.AdjustableCrateScreen;
import com.simibubi.create.content.logistics.item.filter.AbstractFilterScreen;
import com.simibubi.create.content.logistics.item.filter.AttributeFilterScreen;
@ -51,10 +52,12 @@ import com.simibubi.create.foundation.config.ConfigBase.ConfigBool;
import mezz.jei.api.IModPlugin;
import mezz.jei.api.JeiPlugin;
import mezz.jei.api.constants.VanillaRecipeCategoryUid;
import mezz.jei.api.registration.IGuiHandlerRegistration;
import mezz.jei.api.registration.IRecipeCatalystRegistration;
import mezz.jei.api.registration.IRecipeCategoryRegistration;
import mezz.jei.api.registration.IRecipeRegistration;
import mezz.jei.api.registration.IRecipeTransferRegistration;
import mezz.jei.api.runtime.IIngredientManager;
import net.minecraft.client.Minecraft;
import net.minecraft.item.ItemStack;
@ -84,9 +87,9 @@ public class CreateJEI implements IModPlugin {
private final List<CreateRecipeCategory<?>> allCategories = new ArrayList<>();
private final CreateRecipeCategory<?>
milling = register("milling", MillingCategory::new).recipes(AllRecipeTypes.MILLING)
.catalyst(AllBlocks.MILLSTONE::get)
.build(),
milling = register("milling", MillingCategory::new).recipes(AllRecipeTypes.MILLING)
.catalyst(AllBlocks.MILLSTONE::get)
.build(),
crushing = register("crushing", CrushingCategory::new).recipes(AllRecipeTypes.CRUSHING)
.recipesExcluding(AllRecipeTypes.MILLING::getType, AllRecipeTypes.CRUSHING::getType)
@ -167,9 +170,10 @@ public class CreateJEI implements IModPlugin {
.catalyst(AllItems.SAND_PAPER::get)
.catalyst(AllItems.RED_SAND_PAPER::get)
.build(),
deploying = register("deploying", DeployingCategory::new)
.recipeList(() -> DeployerApplicationRecipe.convert(findRecipesByType(AllRecipeTypes.SANDPAPER_POLISHING.type)))
.recipeList(
() -> DeployerApplicationRecipe.convert(findRecipesByType(AllRecipeTypes.SANDPAPER_POLISHING.type)))
.recipes(AllRecipeTypes.DEPLOYING)
.catalyst(AllBlocks.DEPLOYER::get)
.catalyst(AllBlocks.DEPOT::get)
@ -213,6 +217,11 @@ public class CreateJEI implements IModPlugin {
return new CategoryBuilder<T>(name, supplier);
}
@Override
public void registerRecipeTransferHandlers(IRecipeTransferRegistration registration) {
registration.addRecipeTransferHandler(new BlueprintTransferHandler(), VanillaRecipeCategoryUid.CRAFTING);
}
@Override
public void registerCategories(IRecipeCategoryRegistration registration) {
allCategories.forEach(registration::addRecipeCategories);
@ -238,7 +247,8 @@ public class CreateJEI implements IModPlugin {
registration.addGuiContainerHandler(SchematicTableScreen.class, slotMover);
registration.addGuiContainerHandler(FilterScreen.class, slotMover);
registration.addGuiContainerHandler(AttributeFilterScreen.class, slotMover);
registration.addGhostIngredientHandler(AbstractFilterScreen.class, new FilterGhostIngredientHandler());
registration.addGhostIngredientHandler(AbstractFilterScreen.class, new GhostIngredientHandler());
registration.addGhostIngredientHandler(BlueprintScreen.class, new GhostIngredientHandler());
}
private class CategoryBuilder<T extends IRecipe<?>> {
@ -278,12 +288,12 @@ public class CreateJEI implements IModPlugin {
return recipeList(list, null);
}
public CategoryBuilder<T> recipeList(Supplier<List<? extends IRecipe<?>>> list, Function<IRecipe<?>, T> converter) {
public CategoryBuilder<T> recipeList(Supplier<List<? extends IRecipe<?>>> list,
Function<IRecipe<?>, T> converter) {
recipeListConsumers.add(recipes -> {
List<? extends IRecipe<?>> toAdd = list.get();
if (converter != null)
toAdd = toAdd
.stream()
toAdd = toAdd.stream()
.map(converter)
.collect(Collectors.toList());
recipes.addAll(toAdd);

View file

@ -5,12 +5,10 @@ import java.util.List;
import javax.annotation.ParametersAreNonnullByDefault;
import org.apache.logging.log4j.LogManager;
import com.simibubi.create.content.logistics.item.filter.AbstractFilterContainer;
import com.simibubi.create.content.logistics.item.filter.AbstractFilterScreen;
import com.simibubi.create.content.logistics.item.filter.AttributeFilterScreen;
import com.simibubi.create.content.logistics.item.filter.FilterScreenPacket;
import com.simibubi.create.foundation.gui.AbstractSimiContainerScreen;
import com.simibubi.create.foundation.gui.GhostItemContainer;
import com.simibubi.create.foundation.gui.GhostItemSubmitPacket;
import com.simibubi.create.foundation.networking.AllPackets;
import mcp.MethodsReturnNonnullByDefault;
@ -18,21 +16,20 @@ import mezz.jei.api.gui.handlers.IGhostIngredientHandler;
import net.minecraft.client.renderer.Rectangle2d;
import net.minecraft.inventory.container.Slot;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
public class FilterGhostIngredientHandler<T extends AbstractFilterContainer>
implements IGhostIngredientHandler<AbstractFilterScreen<T>> {
public class GhostIngredientHandler<T extends GhostItemContainer<?>>
implements IGhostIngredientHandler<AbstractSimiContainerScreen<T>> {
@Override
public <I> List<Target<I>> getTargets(AbstractFilterScreen<T> gui, I ingredient, boolean doStart) {
public <I> List<Target<I>> getTargets(AbstractSimiContainerScreen<T> gui, I ingredient, boolean doStart) {
List<Target<I>> targets = new ArrayList<>();
boolean isAttributeFilter = gui instanceof AttributeFilterScreen;
if (ingredient instanceof ItemStack) {
for (int i = 36; i < gui.getContainer().inventorySlots.size(); i++) {
targets.add(new FilterGhostTarget<>(gui, i - 36, isAttributeFilter));
targets.add(new GhostTarget<>(gui, i - 36, isAttributeFilter));
// Only accept items in 1st slot. 2nd is used for functionality, don't wanna override that one
if (isAttributeFilter)
@ -52,14 +49,14 @@ public class FilterGhostIngredientHandler<T extends AbstractFilterContainer>
return true;
}
private static class FilterGhostTarget<I, T extends AbstractFilterContainer> implements Target<I> {
private static class GhostTarget<I, T extends GhostItemContainer<?>> implements Target<I> {
private final Rectangle2d area;
private final AbstractFilterScreen<T> gui;
private final AbstractSimiContainerScreen<T> gui;
private final int slotIndex;
private final boolean isAttributeFilter;
public FilterGhostTarget(AbstractFilterScreen<T> gui, int slotIndex, boolean isAttributeFilter) {
public GhostTarget(AbstractSimiContainerScreen<T> gui, int slotIndex, boolean isAttributeFilter) {
this.gui = gui;
this.slotIndex = slotIndex;
this.isAttributeFilter = isAttributeFilter;
@ -75,19 +72,14 @@ public class FilterGhostIngredientHandler<T extends AbstractFilterContainer>
@Override
public void accept(I ingredient) {
ItemStack stack = ((ItemStack) ingredient).copy();
LogManager.getLogger()
.info(stack);
stack.setCount(1);
gui.getContainer().filterInventory.setStackInSlot(slotIndex, stack);
gui.getContainer().ghostInventory.setStackInSlot(slotIndex, stack);
if (isAttributeFilter)
return;
// sync new filter contents with server
CompoundNBT data = new CompoundNBT();
data.putInt("Slot", slotIndex);
data.put("Item", stack.serializeNBT());
AllPackets.channel.sendToServer(new FilterScreenPacket(FilterScreenPacket.Option.UPDATE_FILTER_ITEM, data));
AllPackets.channel.sendToServer(new GhostItemSubmitPacket(stack, slotIndex));
}
}
}

View file

@ -0,0 +1,49 @@
package com.simibubi.create.content.curiosities.tools;
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.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.network.NetworkEvent.Context;
public class BlueprintAssignCompleteRecipePacket extends SimplePacketBase {
private ResourceLocation recipeID;
public BlueprintAssignCompleteRecipePacket(ResourceLocation recipeID) {
this.recipeID = recipeID;
}
public BlueprintAssignCompleteRecipePacket(PacketBuffer buffer) {
recipeID = buffer.readResourceLocation();
}
@Override
public void write(PacketBuffer buffer) {
buffer.writeResourceLocation(recipeID);
}
@Override
public void handle(Supplier<Context> context) {
context.get()
.enqueueWork(() -> {
ServerPlayerEntity player = context.get()
.getSender();
if (player == null)
return;
if (player.openContainer instanceof BlueprintContainer) {
BlueprintContainer c = (BlueprintContainer) player.openContainer;
player.getServerWorld()
.getRecipeManager()
.getRecipe(recipeID)
.ifPresent(r -> BlueprintItem.assignCompleteRecipe(c.ghostInventory, r));
}
});
context.get()
.setPacketHandled(true);
}
}

View file

@ -0,0 +1,172 @@
package com.simibubi.create.content.curiosities.tools;
import java.util.Optional;
import com.simibubi.create.AllContainerTypes;
import com.simibubi.create.content.curiosities.tools.BlueprintEntity.BlueprintSection;
import com.simibubi.create.foundation.gui.GhostItemContainer;
import com.simibubi.create.foundation.gui.IClearableContainer;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.inventory.CraftingInventory;
import net.minecraft.inventory.container.Container;
import net.minecraft.inventory.container.ContainerType;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.ICraftingRecipe;
import net.minecraft.item.crafting.IRecipeType;
import net.minecraft.network.PacketBuffer;
import net.minecraft.network.play.server.SSetSlotPacket;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemStackHandler;
import net.minecraftforge.items.SlotItemHandler;
public class BlueprintContainer extends GhostItemContainer<BlueprintSection> implements IClearableContainer {
public BlueprintContainer(ContainerType<?> type, int id, PlayerInventory inv, PacketBuffer extraData) {
super(type, id, inv, extraData);
}
public BlueprintContainer(ContainerType<?> type, int id, PlayerInventory inv, BlueprintSection section) {
super(type, id, inv, section);
}
public static BlueprintContainer create(int id, PlayerInventory inv, BlueprintSection section) {
return new BlueprintContainer(AllContainerTypes.CRAFTING_BLUEPRINT.get(), id, inv, section);
}
@Override
protected boolean allowRepeats() {
return true;
}
@Override
protected void addSlots() {
addPlayerSlots(33, 137);
int x = 29;
int y = 21;
int index = 0;
for (int row = 0; row < 3; ++row)
for (int col = 0; col < 3; ++col)
this.addSlot(new BlueprintCraftSlot(ghostInventory, index++, x + col * 18, y + row * 18));
addSlot(new BlueprintCraftSlot(ghostInventory, index++, 123, 40));
addSlot(new SlotItemHandler(ghostInventory, index++, 135, 57));
}
public void onCraftMatrixChanged() {
if (contentHolder.getBlueprintWorld().isRemote)
return;
ServerPlayerEntity serverplayerentity = (ServerPlayerEntity) player;
CraftingInventory craftingInventory = new BlueprintCraftingInventory(this, ghostInventory);
Optional<ICraftingRecipe> optional = player.getServer()
.getRecipeManager()
.getRecipe(IRecipeType.CRAFTING, craftingInventory, player.getEntityWorld());
if (!optional.isPresent()) {
if (ghostInventory.getStackInSlot(9)
.isEmpty())
return;
if (!contentHolder.inferredIcon)
return;
ghostInventory.setStackInSlot(9, ItemStack.EMPTY);
serverplayerentity.connection.sendPacket(new SSetSlotPacket(windowId, 36 + 9, ItemStack.EMPTY));
contentHolder.inferredIcon = false;
return;
}
ICraftingRecipe icraftingrecipe = optional.get();
ItemStack itemstack = icraftingrecipe.getCraftingResult(craftingInventory);
ghostInventory.setStackInSlot(9, itemstack);
contentHolder.inferredIcon = true;
ItemStack toSend = itemstack.copy();
toSend.getOrCreateTag()
.putBoolean("InferredFromRecipe", true);
serverplayerentity.connection.sendPacket(new SSetSlotPacket(windowId, 36 + 9, toSend));
}
@Override
public void putStackInSlot(int p_75141_1_, ItemStack p_75141_2_) {
if (p_75141_1_ == 36 + 9) {
if (p_75141_2_.hasTag()) {
contentHolder.inferredIcon = p_75141_2_.getTag()
.getBoolean("InferredFromRecipe");
p_75141_2_.getTag()
.remove("InferredFromRecipe");
} else
contentHolder.inferredIcon = false;
}
super.putStackInSlot(p_75141_1_, p_75141_2_);
}
@Override
protected ItemStackHandler createGhostInventory() {
return contentHolder.getItems();
}
@Override
protected void readData(BlueprintSection contentHolder) {}
@Override
protected void saveData(BlueprintSection contentHolder) {
contentHolder.save(ghostInventory);
}
@Override
@OnlyIn(Dist.CLIENT)
protected BlueprintSection createOnClient(PacketBuffer extraData) {
int entityID = extraData.readVarInt();
int section = extraData.readVarInt();
Entity entityByID = Minecraft.getInstance().world.getEntityByID(entityID);
if (!(entityByID instanceof BlueprintEntity))
return null;
BlueprintEntity blueprintEntity = (BlueprintEntity) entityByID;
BlueprintSection blueprintSection = blueprintEntity.getSection(section);
return blueprintSection;
}
static class BlueprintCraftingInventory extends CraftingInventory {
public BlueprintCraftingInventory(Container container, ItemStackHandler items) {
super(container, 3, 3);
for (int y = 0; y < 3; y++) {
for (int x = 0; x < 3; x++) {
ItemStack stack = items.getStackInSlot(y * 3 + x);
setInventorySlotContents(y * 3 + x, stack == null ? ItemStack.EMPTY : stack.copy());
}
}
}
}
class BlueprintCraftSlot extends SlotItemHandler {
private int index;
public BlueprintCraftSlot(IItemHandler itemHandler, int index, int xPosition, int yPosition) {
super(itemHandler, index, xPosition, yPosition);
this.index = index;
}
@Override
public void onSlotChanged() {
super.onSlotChanged();
if (index == 9 && getHasStack() && !contentHolder.getBlueprintWorld().isRemote) {
contentHolder.inferredIcon = false;
ServerPlayerEntity serverplayerentity = (ServerPlayerEntity) player;
serverplayerentity.connection.sendPacket(new SSetSlotPacket(windowId, 36 + 9, getStack()));
}
if (index < 9)
onCraftMatrixChanged();
}
}
}

View file

@ -0,0 +1,527 @@
package com.simibubi.create.content.curiosities.tools;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import javax.annotation.Nullable;
import org.apache.commons.lang3.Validate;
import com.simibubi.create.AllEntityTypes;
import com.simibubi.create.AllItems;
import com.simibubi.create.Create;
import com.simibubi.create.content.logistics.item.filter.FilterItem;
import com.simibubi.create.content.schematics.ISpecialEntityItemRequirement;
import com.simibubi.create.content.schematics.ItemRequirement;
import com.simibubi.create.content.schematics.ItemRequirement.ItemUseType;
import com.simibubi.create.foundation.networking.ISyncPersistentData;
import com.simibubi.create.foundation.utility.Couple;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.RedstoneDiodeBlock;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntitySize;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.Pose;
import net.minecraft.entity.item.HangingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.inventory.CraftingInventory;
import net.minecraft.inventory.container.Container;
import net.minecraft.inventory.container.INamedContainerProvider;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.ICraftingRecipe;
import net.minecraft.item.crafting.IRecipeType;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.network.IPacket;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.Hand;
import net.minecraft.util.NonNullList;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvents;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.world.GameRules;
import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.common.ForgeHooks;
import net.minecraftforge.common.util.FakePlayer;
import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData;
import net.minecraftforge.fml.hooks.BasicEventHooks;
import net.minecraftforge.fml.network.NetworkHooks;
import net.minecraftforge.items.IItemHandlerModifiable;
import net.minecraftforge.items.ItemStackHandler;
import net.minecraftforge.items.wrapper.InvWrapper;
public class BlueprintEntity extends HangingEntity
implements IEntityAdditionalSpawnData, ISpecialEntityItemRequirement, ISyncPersistentData {
protected int size;
protected Direction verticalOrientation;
@SuppressWarnings("unchecked")
public BlueprintEntity(EntityType<?> p_i50221_1_, World p_i50221_2_) {
super((EntityType<? extends HangingEntity>) p_i50221_1_, p_i50221_2_);
size = 1;
}
public BlueprintEntity(World world, BlockPos pos, Direction facing, Direction verticalOrientation) {
super(AllEntityTypes.CRAFTING_BLUEPRINT.get(), world, pos);
for (int size = 3; size > 0; size--) {
this.size = size;
this.updateFacingWithBoundingBox(facing, verticalOrientation);
if (this.onValidSurface())
break;
}
}
public static EntityType.Builder<?> build(EntityType.Builder<?> builder) {
@SuppressWarnings("unchecked")
EntityType.Builder<BlueprintEntity> entityBuilder = (EntityType.Builder<BlueprintEntity>) builder;
return entityBuilder;
}
@Override
public IPacket<?> createSpawnPacket() {
return NetworkHooks.getEntitySpawningPacket(this);
}
@Override
public void writeAdditional(CompoundNBT p_213281_1_) {
p_213281_1_.putByte("Facing", (byte) this.facingDirection.getIndex());
p_213281_1_.putByte("Orientation", (byte) this.verticalOrientation.getIndex());
p_213281_1_.putInt("Size", size);
super.writeAdditional(p_213281_1_);
}
@Override
public void readAdditional(CompoundNBT p_70037_1_) {
this.facingDirection = Direction.byIndex(p_70037_1_.getByte("Facing"));
this.verticalOrientation = Direction.byIndex(p_70037_1_.getByte("Orientation"));
this.size = p_70037_1_.getInt("Size");
super.readAdditional(p_70037_1_);
this.updateFacingWithBoundingBox(this.facingDirection, this.verticalOrientation);
}
protected void updateFacingWithBoundingBox(Direction facing, Direction verticalOrientation) {
Validate.notNull(facing);
this.facingDirection = facing;
this.verticalOrientation = verticalOrientation;
if (facing.getAxis()
.isHorizontal()) {
this.rotationPitch = 0.0F;
this.rotationYaw = (float) (this.facingDirection.getHorizontalIndex() * 90);
} else {
this.rotationPitch = (float) (-90 * facing.getAxisDirection()
.getOffset());
this.rotationYaw = verticalOrientation.getAxis()
.isHorizontal() ? 180 + verticalOrientation.getHorizontalAngle() : 0;
}
this.prevRotationPitch = this.rotationPitch;
this.prevRotationYaw = this.rotationYaw;
this.updateBoundingBox();
}
@Override
protected float getEyeHeight(Pose p_213316_1_, EntitySize p_213316_2_) {
return 0;
}
@Override
protected void updateBoundingBox() {
if (this.facingDirection == null)
return;
if (this.verticalOrientation == null)
return;
Vector3d pos = Vector3d.of(hangingPosition)
.add(.5, .5, .5)
.subtract(Vector3d.of(facingDirection.getDirectionVec())
.scale(0.46875));
double d1 = pos.x;
double d2 = pos.y;
double d3 = pos.z;
this.setPos(d1, d2, d3);
Axis axis = facingDirection.getAxis();
if (size == 2)
pos = pos.add(Vector3d.of(axis.isHorizontal() ? facingDirection.rotateYCCW()
.getDirectionVec()
: verticalOrientation.rotateY()
.getDirectionVec())
.scale(0.5))
.add(Vector3d
.of(axis.isHorizontal() ? Direction.UP.getDirectionVec()
: facingDirection == Direction.UP ? verticalOrientation.getDirectionVec()
: verticalOrientation.getOpposite()
.getDirectionVec())
.scale(0.5));
d1 = pos.x;
d2 = pos.y;
d3 = pos.z;
double d4 = (double) this.getWidthPixels();
double d5 = (double) this.getHeightPixels();
double d6 = (double) this.getWidthPixels();
Direction.Axis direction$axis = this.facingDirection.getAxis();
switch (direction$axis) {
case X:
d4 = 1.0D;
break;
case Y:
d5 = 1.0D;
break;
case Z:
d6 = 1.0D;
}
d4 = d4 / 32.0D;
d5 = d5 / 32.0D;
d6 = d6 / 32.0D;
this.setBoundingBox(new AxisAlignedBB(d1 - d4, d2 - d5, d3 - d6, d1 + d4, d2 + d5, d3 + d6));
}
public boolean onValidSurface() {
if (!world.isSpaceEmpty(this))
return false;
int i = Math.max(1, this.getWidthPixels() / 16);
int j = Math.max(1, this.getHeightPixels() / 16);
BlockPos blockpos = this.hangingPosition.offset(this.facingDirection.getOpposite());
Direction upDirection = facingDirection.getAxis()
.isHorizontal() ? Direction.UP
: facingDirection == Direction.UP ? verticalOrientation : verticalOrientation.getOpposite();
Direction direction = facingDirection.getAxis()
.isVertical() ? verticalOrientation.rotateY() : facingDirection.rotateYCCW();
BlockPos.Mutable blockpos$mutable = new BlockPos.Mutable();
for (int k = 0; k < i; ++k) {
for (int l = 0; l < j; ++l) {
int i1 = (i - 1) / -2;
int j1 = (j - 1) / -2;
blockpos$mutable.setPos(blockpos)
.move(direction, k + i1)
.move(upDirection, l + j1);
BlockState blockstate = this.world.getBlockState(blockpos$mutable);
if (Block.hasEnoughSolidSide(this.world, blockpos$mutable, this.facingDirection))
continue;
if (!blockstate.getMaterial()
.isSolid() && !RedstoneDiodeBlock.isDiode(blockstate)) {
return false;
}
}
}
return this.world.getEntitiesInAABBexcluding(this, this.getBoundingBox(), IS_HANGING_ENTITY)
.isEmpty();
}
@Override
public int getWidthPixels() {
return 16 * size;
}
@Override
public int getHeightPixels() {
return 16 * size;
}
@Override
public void onBroken(@Nullable Entity p_110128_1_) {
if (!world.getGameRules()
.getBoolean(GameRules.DO_ENTITY_DROPS))
return;
playSound(SoundEvents.ENTITY_PAINTING_BREAK, 1.0F, 1.0F);
if (p_110128_1_ instanceof PlayerEntity) {
PlayerEntity playerentity = (PlayerEntity) p_110128_1_;
if (playerentity.abilities.isCreativeMode) {
return;
}
}
entityDropItem(AllItems.CRAFTING_BLUEPRINT.asStack());
}
@Override
public ItemStack getPickedResult(RayTraceResult target) {
return AllItems.CRAFTING_BLUEPRINT.asStack();
}
@Override
public ItemRequirement getRequiredItems() {
return new ItemRequirement(ItemUseType.CONSUME, AllItems.CRAFTING_BLUEPRINT.get());
}
@Override
public void playPlaceSound() {
this.playSound(SoundEvents.ENTITY_PAINTING_PLACE, 1.0F, 1.0F);
}
@Override
public void setLocationAndAngles(double p_70012_1_, double p_70012_3_, double p_70012_5_, float p_70012_7_,
float p_70012_8_) {
this.setPosition(p_70012_1_, p_70012_3_, p_70012_5_);
}
@Override
@OnlyIn(Dist.CLIENT)
public void setPositionAndRotationDirect(double p_180426_1_, double p_180426_3_, double p_180426_5_,
float p_180426_7_, float p_180426_8_, int p_180426_9_, boolean p_180426_10_) {
BlockPos blockpos =
this.hangingPosition.add(p_180426_1_ - this.getX(), p_180426_3_ - this.getY(), p_180426_5_ - this.getZ());
this.setPosition((double) blockpos.getX(), (double) blockpos.getY(), (double) blockpos.getZ());
}
@Override
public void writeSpawnData(PacketBuffer buffer) {
CompoundNBT compound = new CompoundNBT();
writeAdditional(compound);
buffer.writeCompoundTag(compound);
buffer.writeCompoundTag(getPersistentData());
}
@Override
public void readSpawnData(PacketBuffer additionalData) {
readAdditional(additionalData.readCompoundTag());
getPersistentData().merge(additionalData.readCompoundTag());
}
@Override
public ActionResultType applyPlayerInteraction(PlayerEntity player, Vector3d vec, Hand hand) {
if (player instanceof FakePlayer)
return ActionResultType.PASS;
BlueprintSection section = getSectionAt(vec);
if (!AllItems.WRENCH.isIn(player.getHeldItem(hand)) && !world.isRemote) {
boolean empty = true;
ItemStackHandler items = section.getItems();
for (int i = 0; i < 9; i++) {
if (!items.getStackInSlot(i)
.isEmpty()) {
empty = false;
break;
}
}
if (!empty) {
IItemHandlerModifiable playerInv = new InvWrapper(player.inventory);
boolean firstPass = true;
int amountCrafted = 0;
ForgeHooks.setCraftingPlayer(player);
Optional<ICraftingRecipe> recipe = Optional.empty();
do {
Map<Integer, ItemStack> stacksTaken = new HashMap<>();
Map<Integer, ItemStack> craftingGrid = new HashMap<>();
boolean success = true;
Search: for (int i = 0; i < 9; i++) {
ItemStack requestedItem = items.getStackInSlot(i);
if (requestedItem.isEmpty()) {
craftingGrid.put(i, ItemStack.EMPTY);
continue;
}
for (int slot = 0; slot < playerInv.getSlots(); slot++) {
if (!FilterItem.test(world, playerInv.getStackInSlot(slot), requestedItem))
continue;
ItemStack currentItem = playerInv.extractItem(slot, 1, false);
if (stacksTaken.containsKey(slot)) {
stacksTaken.get(slot)
.grow(1);
} else {
stacksTaken.put(slot, currentItem.copy());
}
craftingGrid.put(i, currentItem);
continue Search;
}
success = false;
break;
}
if (success) {
CraftingInventory craftingInventory = new BlueprintCraftingInventory(craftingGrid);
if (!recipe.isPresent())
recipe = world.getRecipeManager()
.getRecipe(IRecipeType.CRAFTING, craftingInventory, world);
ItemStack result = recipe.filter(r -> r.matches(craftingInventory, world))
.map(r -> r.getCraftingResult(craftingInventory))
.orElse(ItemStack.EMPTY);
if (result.isEmpty()) {
success = false;
} else if (result.getCount() + amountCrafted > 64) {
success = false;
} else {
amountCrafted += result.getCount();
result.onCrafting(player.world, player, 1);
BasicEventHooks.firePlayerCraftingEvent(player, result, craftingInventory);
NonNullList<ItemStack> nonnulllist = world.getRecipeManager()
.getRecipeNonNull(IRecipeType.CRAFTING, craftingInventory, world);
if (firstPass)
world.playSound(null, player.getBlockPos(), SoundEvents.ENTITY_ITEM_PICKUP,
SoundCategory.PLAYERS, .2f, 1f + Create.RANDOM.nextFloat());
player.inventory.placeItemBackInInventory(world, result);
for (ItemStack itemStack : nonnulllist)
player.inventory.placeItemBackInInventory(world, itemStack);
firstPass = false;
}
}
if (!success) {
for (Entry<Integer, ItemStack> entry : stacksTaken.entrySet())
playerInv.insertItem(entry.getKey(), entry.getValue(), false);
break;
}
} while (player.isSneaking());
ForgeHooks.setCraftingPlayer(null);
return ActionResultType.SUCCESS;
}
}
int i = section.index;
if (!world.isRemote && player instanceof ServerPlayerEntity) {
NetworkHooks.openGui((ServerPlayerEntity) player, section, buf -> {
buf.writeVarInt(getEntityId());
buf.writeVarInt(i);
});
}
return ActionResultType.SUCCESS;
}
public BlueprintSection getSectionAt(Vector3d vec) {
int index = 0;
if (size > 1) {
vec = VecHelper.rotate(vec, rotationYaw, Axis.Y);
vec = VecHelper.rotate(vec, -rotationPitch, Axis.X);
vec = vec.add(0.5, 0.5, 0);
if (size == 3)
vec = vec.add(1, 1, 0);
int x = MathHelper.clamp(MathHelper.floor(vec.x), 0, size - 1);
int y = MathHelper.clamp(MathHelper.floor(vec.y), 0, size - 1);
index = x + y * size;
}
BlueprintSection section = getSection(index);
return section;
}
static class BlueprintCraftingInventory extends CraftingInventory {
private static Container dummyContainer = new Container(null, -1) {
public boolean canInteractWith(PlayerEntity playerIn) {
return false;
}
};
public BlueprintCraftingInventory(Map<Integer, ItemStack> items) {
super(dummyContainer, 3, 3);
for (int y = 0; y < 3; y++) {
for (int x = 0; x < 3; x++) {
ItemStack stack = items.get(y * 3 + x);
setInventorySlotContents(y * 3 + x, stack == null ? ItemStack.EMPTY : stack.copy());
}
}
}
}
public CompoundNBT getOrCreateRecipeCompound() {
CompoundNBT persistentData = getPersistentData();
if (!persistentData.contains("Recipes"))
persistentData.put("Recipes", new CompoundNBT());
return persistentData.getCompound("Recipes");
}
private Map<Integer, BlueprintSection> sectionCache = new HashMap<>();
public BlueprintSection getSection(int index) {
return sectionCache.computeIfAbsent(index, i -> new BlueprintSection(i));
}
class BlueprintSection implements INamedContainerProvider {
int index;
Couple<ItemStack> cachedDisplayItems;
public boolean inferredIcon = false;
public BlueprintSection(int index) {
this.index = index;
}
public Couple<ItemStack> getDisplayItems() {
if (cachedDisplayItems != null)
return cachedDisplayItems;
ItemStackHandler items = getItems();
return cachedDisplayItems = Couple.create(items.getStackInSlot(9), items.getStackInSlot(10));
}
public ItemStackHandler getItems() {
ItemStackHandler newInv = new ItemStackHandler(11);
CompoundNBT list = getOrCreateRecipeCompound();
CompoundNBT invNBT = list.getCompound(index + "");
inferredIcon = list.getBoolean("InferredIcon");
if (!invNBT.isEmpty())
newInv.deserializeNBT(invNBT);
return newInv;
}
public void save(ItemStackHandler inventory) {
CompoundNBT list = getOrCreateRecipeCompound();
list.put(index + "", inventory.serializeNBT());
list.putBoolean("InferredIcon", inferredIcon);
cachedDisplayItems = null;
if (!world.isRemote)
syncPersistentDataWithTracking(BlueprintEntity.this);
}
public boolean isEntityAlive() {
return isAlive();
}
public World getBlueprintWorld() {
return world;
}
@Override
public Container createMenu(int id, PlayerInventory inv, PlayerEntity player) {
return BlueprintContainer.create(id, inv, this);
}
@Override
public ITextComponent getDisplayName() {
return new StringTextComponent("");
}
}
@Override
public void onPersistentDataUpdated() {
sectionCache.clear();
}
}

View file

@ -0,0 +1,154 @@
package com.simibubi.create.content.curiosities.tools;
import java.util.Collection;
import com.simibubi.create.AllItems;
import com.simibubi.create.content.logistics.item.filter.AttributeFilterContainer.WhitelistMode;
import com.simibubi.create.content.logistics.item.filter.FilterItem;
import com.simibubi.create.content.logistics.item.filter.ItemAttribute;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.item.HangingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUseContext;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.item.crafting.Ingredient.IItemList;
import net.minecraft.item.crafting.Ingredient.SingleItemList;
import net.minecraft.item.crafting.Ingredient.TagList;
import net.minecraft.item.crafting.ShapedRecipe;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.ListNBT;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction;
import net.minecraft.util.JSONUtils;
import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.common.crafting.StackList;
import net.minecraftforge.fml.common.ObfuscationReflectionHelper;
import net.minecraftforge.items.ItemStackHandler;
public class BlueprintItem extends Item {
public BlueprintItem(Properties p_i48487_1_) {
super(p_i48487_1_);
}
@Override
public ActionResultType onItemUse(ItemUseContext ctx) {
Direction face = ctx.getFace();
PlayerEntity player = ctx.getPlayer();
ItemStack stack = ctx.getItem();
BlockPos pos = ctx.getPos()
.offset(face);
if (player != null && !player.canPlayerEdit(pos, face, stack))
return ActionResultType.FAIL;
World world = ctx.getWorld();
HangingEntity hangingentity = new BlueprintEntity(world, pos, face, face.getAxis()
.isHorizontal() ? Direction.DOWN : ctx.getPlacementHorizontalFacing());
CompoundNBT compoundnbt = stack.getTag();
if (compoundnbt != null)
EntityType.applyItemNBT(world, player, hangingentity, compoundnbt);
if (!hangingentity.onValidSurface())
return ActionResultType.CONSUME;
if (!world.isRemote) {
hangingentity.playPlaceSound();
world.addEntity(hangingentity);
}
stack.shrink(1);
return ActionResultType.success(world.isRemote);
}
protected boolean canPlace(PlayerEntity p_200127_1_, Direction p_200127_2_, ItemStack p_200127_3_,
BlockPos p_200127_4_) {
return p_200127_1_.canPlayerEdit(p_200127_4_, p_200127_2_, p_200127_3_);
}
public static void assignCompleteRecipe(ItemStackHandler inv, IRecipe<?> recipe) {
NonNullList<Ingredient> ingredients = recipe.getIngredients();
for (int i = 0; i < 9; i++)
inv.setStackInSlot(i, ItemStack.EMPTY);
inv.setStackInSlot(9, recipe.getRecipeOutput());
if (recipe instanceof ShapedRecipe) {
ShapedRecipe shapedRecipe = (ShapedRecipe) recipe;
for (int row = 0; row < shapedRecipe.getHeight(); row++)
for (int col = 0; col < shapedRecipe.getWidth(); col++)
inv.setStackInSlot(row * 3 + col,
convertIngredientToFilter(ingredients.get(row * shapedRecipe.getWidth() + col)));
} else {
for (int i = 0; i < ingredients.size(); i++)
inv.setStackInSlot(i, convertIngredientToFilter(ingredients.get(i)));
}
}
private static ItemStack convertIngredientToFilter(Ingredient ingredient) {
Ingredient.IItemList[] acceptedItems =
ObfuscationReflectionHelper.getPrivateValue(Ingredient.class, ingredient, "field_199807_b");
if (acceptedItems == null || acceptedItems.length > 18)
return ItemStack.EMPTY;
if (acceptedItems.length == 0)
return ItemStack.EMPTY;
if (acceptedItems.length == 1)
return convertIItemListToFilter(acceptedItems[0]);
ItemStack result = AllItems.FILTER.asStack();
ItemStackHandler filterItems = FilterItem.getFilterItems(result);
for (int i = 0; i < acceptedItems.length; i++)
filterItems.setStackInSlot(i, convertIItemListToFilter(acceptedItems[i]));
result.getOrCreateTag()
.put("Items", filterItems.serializeNBT());
return result;
}
private static ItemStack convertIItemListToFilter(IItemList itemList) {
Collection<ItemStack> stacks = itemList.getStacks();
if (itemList instanceof SingleItemList) {
for (ItemStack itemStack : stacks)
return itemStack;
}
if (itemList instanceof TagList) {
ResourceLocation resourcelocation = new ResourceLocation(JSONUtils.getString(itemList.serialize(), "tag"));
ItemStack filterItem = AllItems.ATTRIBUTE_FILTER.asStack();
filterItem.getOrCreateTag()
.putInt("WhitelistMode", WhitelistMode.WHITELIST_DISJ.ordinal());
ListNBT attributes = new ListNBT();
ItemAttribute at = new ItemAttribute.InTag(resourcelocation);
CompoundNBT compoundNBT = new CompoundNBT();
at.serializeNBT(compoundNBT);
compoundNBT.putBoolean("Inverted", false);
attributes.add(compoundNBT);
filterItem.getOrCreateTag()
.put("MatchedAttributes", attributes);
return filterItem;
}
if (itemList instanceof StackList) {
ItemStack result = AllItems.FILTER.asStack();
ItemStackHandler filterItems = FilterItem.getFilterItems(result);
int i = 0;
for (ItemStack itemStack : stacks) {
if (i >= 18)
break;
filterItems.setStackInSlot(i++, itemStack);
}
CompoundNBT tag = result.getOrCreateTag();
tag.put("Items", filterItems.serializeNBT());
tag.putBoolean("RespectNBT", true);
return result;
}
return ItemStack.EMPTY;
}
}

View file

@ -0,0 +1,240 @@
package com.simibubi.create.content.curiosities.tools;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.content.curiosities.tools.BlueprintEntity.BlueprintCraftingInventory;
import com.simibubi.create.content.curiosities.tools.BlueprintEntity.BlueprintSection;
import com.simibubi.create.content.logistics.item.filter.FilterItem;
import com.simibubi.create.foundation.gui.AllGuiTextures;
import com.simibubi.create.foundation.gui.GuiGameElement;
import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.Pair;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.inventory.CraftingInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.item.crafting.ICraftingRecipe;
import net.minecraft.item.crafting.IRecipeType;
import net.minecraft.util.math.EntityRayTraceResult;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.RayTraceResult.Type;
import net.minecraft.util.text.TextFormatting;
import net.minecraftforge.items.ItemHandlerHelper;
import net.minecraftforge.items.ItemStackHandler;
public class BlueprintOverlayRenderer {
static boolean active;
static boolean empty;
static boolean lastSneakState;
static BlueprintSection lastTargetedSection;
static List<Pair<ItemStack, Boolean>> ingredients = new ArrayList<>();
static ItemStack result = ItemStack.EMPTY;
static boolean resultCraftable = false;
public static void tick() {
Minecraft mc = Minecraft.getInstance();
RayTraceResult mouseOver = mc.objectMouseOver;
BlueprintSection last = lastTargetedSection;
boolean sneak = mc.player.isSneaking();
lastTargetedSection = null;
active = false;
if (mouseOver == null)
return;
if (mouseOver.getType() != Type.ENTITY)
return;
EntityRayTraceResult entityRay = (EntityRayTraceResult) mouseOver;
if (!(entityRay.getEntity() instanceof BlueprintEntity))
return;
BlueprintEntity blueprintEntity = (BlueprintEntity) entityRay.getEntity();
BlueprintSection sectionAt = blueprintEntity.getSectionAt(entityRay.getHitVec()
.subtract(blueprintEntity.getPositionVec()));
lastTargetedSection = last;
active = true;
if (sectionAt != lastTargetedSection || AnimationTickHolder.getTicks() % 10 == 0 || lastSneakState != sneak)
rebuild(sectionAt, sneak);
lastTargetedSection = sectionAt;
lastSneakState = sneak;
}
public static void rebuild(BlueprintSection sectionAt, boolean sneak) {
ItemStackHandler items = sectionAt.getItems();
boolean empty = true;
for (int i = 0; i < 9; i++) {
if (!items.getStackInSlot(i)
.isEmpty()) {
empty = false;
break;
}
}
BlueprintOverlayRenderer.empty = empty;
BlueprintOverlayRenderer.result = ItemStack.EMPTY;
if (empty)
return;
boolean firstPass = true;
boolean success = true;
Minecraft mc = Minecraft.getInstance();
ItemStackHandler playerInv = new ItemStackHandler(mc.player.inventory.getSizeInventory());
for (int i = 0; i < playerInv.getSlots(); i++)
playerInv.setStackInSlot(i, mc.player.inventory.getStackInSlot(i)
.copy());
int amountCrafted = 0;
Optional<ICraftingRecipe> recipe = Optional.empty();
Map<Integer, ItemStack> craftingGrid = new HashMap<>();
ingredients.clear();
ItemStackHandler missingItems = new ItemStackHandler(64);
ItemStackHandler availableItems = new ItemStackHandler(64);
List<ItemStack> newlyAdded = new ArrayList<>();
List<ItemStack> newlyMissing = new ArrayList<>();
boolean invalid = false;
do {
craftingGrid.clear();
newlyAdded.clear();
newlyMissing.clear();
Search: for (int i = 0; i < 9; i++) {
ItemStack requestedItem = items.getStackInSlot(i);
if (requestedItem.isEmpty()) {
craftingGrid.put(i, ItemStack.EMPTY);
continue;
}
for (int slot = 0; slot < playerInv.getSlots(); slot++) {
if (!FilterItem.test(mc.world, playerInv.getStackInSlot(slot), requestedItem))
continue;
ItemStack currentItem = playerInv.extractItem(slot, 1, false);
craftingGrid.put(i, currentItem);
newlyAdded.add(currentItem);
continue Search;
}
success = false;
newlyMissing.add(requestedItem);
}
if (success) {
CraftingInventory craftingInventory = new BlueprintCraftingInventory(craftingGrid);
if (!recipe.isPresent())
recipe = mc.world.getRecipeManager()
.getRecipe(IRecipeType.CRAFTING, craftingInventory, mc.world);
ItemStack resultFromRecipe = recipe.filter(r -> r.matches(craftingInventory, mc.world))
.map(r -> r.getCraftingResult(craftingInventory))
.orElse(ItemStack.EMPTY);
if (resultFromRecipe.isEmpty()) {
if (!recipe.isPresent())
invalid = true;
success = false;
} else if (resultFromRecipe.getCount() + amountCrafted > 64) {
success = false;
} else {
amountCrafted += resultFromRecipe.getCount();
if (result.isEmpty())
result = resultFromRecipe.copy();
else
result.grow(resultFromRecipe.getCount());
resultCraftable = true;
firstPass = false;
}
}
if (success || firstPass) {
newlyAdded.forEach(s -> ItemHandlerHelper.insertItemStacked(availableItems, s, false));
newlyMissing.forEach(s -> ItemHandlerHelper.insertItemStacked(missingItems, s, false));
}
if (!success) {
if (firstPass) {
result = invalid ? ItemStack.EMPTY : items.getStackInSlot(9);
resultCraftable = false;
}
break;
}
if (!sneak)
break;
} while (success);
for (int i = 0; i < 9; i++) {
ItemStack available = availableItems.getStackInSlot(i);
if (available.isEmpty())
continue;
ingredients.add(Pair.of(available, true));
}
for (int i = 0; i < 9; i++) {
ItemStack missing = missingItems.getStackInSlot(i);
if (missing.isEmpty())
continue;
ingredients.add(Pair.of(missing, false));
}
}
public static void renderOverlay(MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay,
float partialTicks) {
if (!active || empty)
return;
Minecraft mc = Minecraft.getInstance();
int w = 30 + 21 * ingredients.size() + 21;
int x = (mc.getWindow()
.getScaledWidth() - w) / 2;
int y = (int) (mc.getWindow()
.getScaledHeight() / 3f * 2);
for (Pair<ItemStack, Boolean> pair : ingredients) {
RenderSystem.enableBlend();
(pair.getSecond() ? AllGuiTextures.HOTSLOT_ACTIVE : AllGuiTextures.HOTSLOT).draw(ms, x, y);
ItemStack itemStack = pair.getFirst();
GuiGameElement.of(itemStack)
.at(x + 3, y + 3)
.render(ms);
mc.getItemRenderer()
.renderItemOverlayIntoGUI(mc.fontRenderer, itemStack, x + 3, y + 3,
pair.getSecond() || itemStack.getCount() == 1 ? null
: TextFormatting.GOLD.toString() + itemStack.getCount());
x += 21;
}
x += 5;
RenderSystem.enableBlend();
AllGuiTextures.HOTSLOT_ARROW.draw(ms, x, y + 4);
x += 25;
if (result.isEmpty()) {
AllGuiTextures.HOTSLOT.draw(ms, x, y);
GuiGameElement.of(Items.BARRIER)
.at(x + 3, y + 3)
.render(ms);
} else {
(resultCraftable ? AllGuiTextures.HOTSLOT_SUPER_ACTIVE : AllGuiTextures.HOTSLOT).draw(ms,
resultCraftable ? x - 1 : x, resultCraftable ? y - 1 : y);
GuiGameElement.of(result)
.at(x + 3, y + 3)
.render(ms);
mc.getItemRenderer()
.renderItemOverlayIntoGUI(mc.fontRenderer, result, x + 3, y + 3, null);
}
}
}

View file

@ -0,0 +1,116 @@
package com.simibubi.create.content.curiosities.tools;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.AllBlockPartials;
import com.simibubi.create.content.curiosities.tools.BlueprintEntity.BlueprintSection;
import com.simibubi.create.foundation.render.PartialBufferer;
import com.simibubi.create.foundation.render.SuperByteBuffer;
import com.simibubi.create.foundation.render.backend.core.PartialModel;
import com.simibubi.create.foundation.utility.Couple;
import com.simibubi.create.foundation.utility.MatrixStacker;
import net.minecraft.block.Blocks;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.renderer.entity.EntityRenderer;
import net.minecraft.client.renderer.entity.EntityRendererManager;
import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.vector.Matrix3f;
public class BlueprintRenderer extends EntityRenderer<BlueprintEntity> {
public BlueprintRenderer(EntityRendererManager p_i46179_1_) {
super(p_i46179_1_);
}
@Override
public void render(BlueprintEntity entity, float yaw, float pt, MatrixStack ms, IRenderTypeBuffer buffer,
int overlay) {
PartialModel partialModel = entity.size == 3 ? AllBlockPartials.CRAFTING_BLUEPRINT_3x3
: entity.size == 2 ? AllBlockPartials.CRAFTING_BLUEPRINT_2x2 : AllBlockPartials.CRAFTING_BLUEPRINT_1x1;
SuperByteBuffer sbb = PartialBufferer.get(partialModel, Blocks.AIR.getDefaultState());
int light = WorldRenderer.getLightmapCoordinates(entity.world, entity.getBlockPos());
sbb.matrixStacker()
.rotateY(-yaw)
.rotateX(90.0F + entity.rotationPitch)
.translate(-.5, -1 / 32f, -.5);
if (entity.size == 2)
sbb.translate(.5, 0, -.5);
sbb.light(light)
.renderInto(ms, buffer.getBuffer(RenderType.getSolid()));
super.render(entity, yaw, pt, ms, buffer, light);
ms.push();
MatrixStacker.of(ms)
.rotateY(-yaw)
.rotateX(entity.rotationPitch == -90 ? -45 : entity.rotationPitch == 0 ? -15 : -5);
Matrix3f copy = ms.peek()
.getNormal()
.copy();
ms.pop();
ms.push();
MatrixStacker.of(ms)
.rotateY(-yaw)
.rotateX(entity.rotationPitch)
.translate(0, 0, 1 / 32f + .001);
if (entity.size == 3)
ms.translate(-1, -1, 0);
for (int x = 0; x < entity.size; x++) {
ms.push();
for (int y = 0; y < entity.size; y++) {
BlueprintSection section = entity.getSection(x * entity.size + y);
Couple<ItemStack> displayItems = section.getDisplayItems();
ms.push();
ms.scale(.5f, .5f, 1 / 1024f);
displayItems.forEachWithContext((stack, primary) -> {
if (stack.isEmpty())
return;
ms.push();
if (!primary) {
ms.translate(0.325f, -0.325f, 1);
ms.scale(.625f, .625f, 1);
}
Matrix3f n = ms.peek()
.getNormal();
n.a00 = copy.a00;
n.a01 = copy.a01;
n.a02 = copy.a02;
n.a10 = copy.a10;
n.a11 = copy.a11;
n.a12 = copy.a12;
n.a20 = copy.a20;
n.a21 = copy.a21;
n.a22 = copy.a22;
Minecraft.getInstance()
.getItemRenderer()
.renderItem(stack, TransformType.GUI, light, overlay, ms, buffer);
ms.pop();
});
ms.pop();
ms.translate(1, 0, 0);
}
ms.pop();
ms.translate(0, 1, 0);
}
ms.pop();
}
@Override
public ResourceLocation getEntityTexture(BlueprintEntity p_110775_1_) {
return null;
}
}

View file

@ -0,0 +1,192 @@
package com.simibubi.create.content.curiosities.tools;
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.AllBlockPartials;
import com.simibubi.create.AllItems;
import com.simibubi.create.content.logistics.item.filter.FilterScreenPacket;
import com.simibubi.create.content.logistics.item.filter.FilterScreenPacket.Option;
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.networking.AllPackets;
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 BlueprintScreen extends AbstractSimiContainerScreen<BlueprintContainer> {
protected AllGuiTextures background;
private List<Rectangle2d> extraAreas = Collections.emptyList();
private IconButton resetButton;
private IconButton confirmButton;
public BlueprintScreen(BlueprintContainer container, PlayerInventory inv, ITextComponent title) {
super(container, inv, title);
this.background = AllGuiTextures.BLUEPRINT;
}
@Override
protected void init() {
setWindowSize(background.width + 50, background.height + PLAYER_INVENTORY.height + 20);
super.init();
widgets.clear();
int x = guiLeft;
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 - 62, guiTop + background.height - 24, AllIcons.I_TRASH);
confirmButton = new IconButton(x + background.width - 33, guiTop + background.height - 24, 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;
background.draw(ms, this, x, y);
int invX = guiLeft + 25;
int invY = y + background.height + 10;
PLAYER_INVENTORY.draw(ms, this, invX, invY);
String localizedName = I18n.format(AllItems.CRAFTING_BLUEPRINT.get()
.getTranslationKey());
textRenderer.draw(ms, playerInventory.getDisplayName(), invX + 7, invY + 6, 0x666666);
textRenderer.draw(ms, localizedName, x + 15, y + 4, 0xFFFFFF);
GuiGameElement.of(AllBlockPartials.CRAFTING_BLUEPRINT_1x1).<GuiGameElement
.GuiRenderBuilder>at(x + background.width + 20, guiTop + background.height - 35, 0)
.rotate(45, -45, 22.5f)
.scale(40)
.render(ms);
}
@Override
protected void drawMouseoverTooltip(MatrixStack ms, int x, int y) {
if (!this.client.player.inventory.getItemStack()
.isEmpty() || this.hoveredSlot == null || this.hoveredSlot.getHasStack()
|| hoveredSlot.inventory == container.playerInventory) {
super.drawMouseoverTooltip(ms, x, y);
return;
}
renderWrappedToolTip(ms, addToTooltip(new LinkedList<>(), hoveredSlot.getSlotIndex(), true), x, y,
textRenderer);
}
@Override
public List<ITextComponent> getTooltipFromItem(ItemStack stack) {
List<ITextComponent> list = super.getTooltipFromItem(stack);
if (hoveredSlot.inventory == container.playerInventory)
return list;
return hoveredSlot != null ? addToTooltip(list, hoveredSlot.getSlotIndex(), false) : list;
}
private List<ITextComponent> addToTooltip(List<ITextComponent> list, int slot, boolean isEmptySlot) {
if (slot < 0 || slot > 10)
return list;
if (slot < 9) {
list.add(Lang.createTranslationTextComponent("crafting_blueprint.crafting_slot")
.formatted(TextFormatting.GOLD));
if (isEmptySlot)
list.add(Lang.createTranslationTextComponent("crafting_blueprint.filter_items_viable")
.formatted(TextFormatting.GRAY));
} else if (slot == 9) {
list.add(Lang.createTranslationTextComponent("crafting_blueprint.display_slot")
.formatted(TextFormatting.GOLD));
if (!isEmptySlot)
list.add(Lang
.createTranslationTextComponent("crafting_blueprint."
+ (container.contentHolder.inferredIcon ? "inferred" : "manually_assigned"))
.formatted(TextFormatting.GRAY));
} else if (slot == 10) {
list.add(Lang.createTranslationTextComponent("crafting_blueprint.secondary_display_slot")
.formatted(TextFormatting.GOLD));
if (isEmptySlot)
list.add(Lang.createTranslationTextComponent("crafting_blueprint.optional")
.formatted(TextFormatting.GRAY));
}
return list;
}
@Override
public void tick() {
// handleTooltips();
super.tick();
if (!container.contentHolder.isEntityAlive())
client.player.closeScreen();
}
// protected void handleTooltips() {
// List<IconButton> tooltipButtons = getTooltipButtons();
//
// for (IconButton button : tooltipButtons) {
// if (!button.getToolTip()
// .isEmpty()) {
// button.setToolTip(button.getToolTip()
// .get(0));
// button.getToolTip()
// .add(TooltipHelper.holdShift(Palette.Yellow, hasShiftDown()));
// }
// }
//
// if (hasShiftDown()) {
// List<IFormattableTextComponent> tooltipDescriptions = getTooltipDescriptions();
// for (int i = 0; i < tooltipButtons.size(); i++)
// fillToolTip(tooltipButtons.get(i), tooltipDescriptions.get(i));
// }
// }
@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();
contentsCleared();
container.sendClearPacket();
return true;
}
}
return mouseClicked;
}
protected void contentsCleared() {}
protected void sendOptionUpdate(Option option) {
AllPackets.channel.sendToServer(new FilterScreenPacket(option));
}
@Override
public List<Rectangle2d> getExtraAreas() {
return extraAreas;
}
}

View file

@ -38,7 +38,8 @@ public class LinkedControllerScreen extends AbstractSimiContainerScreen<LinkedCo
@Override
protected void drawMouseoverTooltip(MatrixStack ms, int x, int y) {
if (!this.client.player.inventory.getItemStack()
.isEmpty() || this.hoveredSlot == null || this.hoveredSlot.getHasStack()) {
.isEmpty() || this.hoveredSlot == null || this.hoveredSlot.getHasStack()
|| hoveredSlot.inventory == container.playerInventory) {
super.drawMouseoverTooltip(ms, x, y);
return;
}
@ -48,6 +49,8 @@ public class LinkedControllerScreen extends AbstractSimiContainerScreen<LinkedCo
@Override
public List<ITextComponent> getTooltipFromItem(ItemStack stack) {
List<ITextComponent> list = super.getTooltipFromItem(stack);
if (hoveredSlot.inventory == container.playerInventory)
return list;
return hoveredSlot != null ? addToTooltip(list, hoveredSlot.getSlotIndex()) : list;
}

View file

@ -1,145 +1,58 @@
package com.simibubi.create.content.logistics.item.filter;
import com.simibubi.create.foundation.gui.IClearableContainer;
import com.simibubi.create.foundation.gui.GhostItemContainer;
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.ItemHandlerHelper;
import net.minecraftforge.items.ItemStackHandler;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
public abstract class AbstractFilterContainer extends Container implements IClearableContainer {
public PlayerEntity player;
protected PlayerInventory playerInventory;
public ItemStack filterItem;
public ItemStackHandler filterInventory;
public abstract class AbstractFilterContainer extends GhostItemContainer<ItemStack> {
protected AbstractFilterContainer(ContainerType<?> type, int id, PlayerInventory inv, PacketBuffer extraData) {
this(type, id, inv, extraData.readItemStack());
super(type, id, inv, extraData);
}
protected AbstractFilterContainer(ContainerType<?> type, int id, PlayerInventory inv, ItemStack filterItem) {
super(type, id);
player = inv.player;
playerInventory = inv;
this.filterItem = filterItem;
init();
}
protected void init() {
this.filterInventory = createFilterInventory();
readData(filterItem);
addPlayerSlots();
addFilterSlots();
detectAndSendChanges();
}
@Override
public void clearContents() {
for (int i = 0; i < filterInventory.getSlots(); i++)
filterInventory.setStackInSlot(i, ItemStack.EMPTY);
}
protected abstract int getInventoryOffset();
protected abstract void addFilterSlots();
protected abstract ItemStackHandler createFilterInventory();
protected abstract void readData(ItemStack filterItem);
protected abstract void saveData(ItemStack filterItem);
protected void addPlayerSlots() {
int x = 8;
int y = 28 + getInventoryOffset();
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));
}
@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;
protected AbstractFilterContainer(ContainerType<?> type, int id, PlayerInventory inv, ItemStack contentHolder) {
super(type, id, inv, contentHolder);
}
@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;
return super.slotClick(slotId, dragType, clickTypeIn, player);
}
@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 (ItemHandlerHelper.canItemStacksStack(stack, stackToInsert))
break;
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;
protected boolean allowRepeats() {
return false;
}
@Override
public void onContainerClosed(PlayerEntity playerIn) {
super.onContainerClosed(playerIn);
filterItem.getOrCreateTag().put("Items", filterInventory.serializeNBT());
saveData(filterItem);
@OnlyIn(Dist.CLIENT)
protected ItemStack createOnClient(PacketBuffer extraData) {
return extraData.readItemStack();
}
protected abstract int getPlayerInventoryXOffset();
protected abstract void addFilterSlots();
@Override
protected void addSlots() {
addPlayerSlots(8, 28 + getPlayerInventoryXOffset());
addFilterSlots();
}
@Override
protected void saveData(ItemStack contentHolder) {
contentHolder.getOrCreateTag()
.put("Items", ghostInventory.serializeNBT());
}
}

View file

@ -66,9 +66,9 @@ public abstract class AbstractFilterScreen<F extends AbstractFilterContainer> ex
int invY = y + background.height + 10;
PLAYER_INVENTORY.draw(ms, this, invX, invY);
textRenderer.draw(ms, playerInventory.getDisplayName(), invX + 7, invY + 6, 0x666666);
textRenderer.draw(ms, I18n.format(container.filterItem.getTranslationKey()), x + 15, y + 3, 0xdedede);
textRenderer.draw(ms, I18n.format(container.contentHolder.getTranslationKey()), x + 15, y + 3, 0xdedede);
GuiGameElement.of(container.filterItem)
GuiGameElement.of(container.contentHolder)
.<GuiGameElement.GuiRenderBuilder>at(x + background.width, guiTop + background.height - 60, -200)
.scale(5)
.render(ms);
@ -82,7 +82,7 @@ public abstract class AbstractFilterScreen<F extends AbstractFilterContainer> ex
handleIndicators();
if (!container.player.getHeldItemMainhand()
.equals(container.filterItem, false))
.equals(container.contentHolder, false))
client.player.closeScreen();
}

View file

@ -53,22 +53,22 @@ public class AttributeFilterContainer extends AbstractFilterContainer {
}
@Override
protected void init() {
super.init();
protected void init(PlayerInventory inv, ItemStack contentHolder) {
super.init(inv, contentHolder);
ItemStack stack = new ItemStack(Items.NAME_TAG);
stack.setDisplayName(
new StringTextComponent("Selected Tags").formatted(TextFormatting.RESET, TextFormatting.BLUE));
filterInventory.setStackInSlot(1, stack);
ghostInventory.setStackInSlot(1, stack);
}
@Override
protected ItemStackHandler createFilterInventory() {
protected ItemStackHandler createGhostInventory() {
return new ItemStackHandler(2);
}
protected void addFilterSlots() {
this.addSlot(new SlotItemHandler(filterInventory, 0, -34, 22));
this.addSlot(new SlotItemHandler(filterInventory, 1, -28, 57) {
this.addSlot(new SlotItemHandler(ghostInventory, 0, -34, 22));
this.addSlot(new SlotItemHandler(ghostInventory, 1, -28, 57) {
@Override
public boolean canTakeStack(PlayerEntity playerIn) {
return false;
@ -102,20 +102,20 @@ public class AttributeFilterContainer extends AbstractFilterContainer {
if (index == 37)
return ItemStack.EMPTY;
if (index == 36) {
filterInventory.setStackInSlot(37, ItemStack.EMPTY);
ghostInventory.setStackInSlot(37, ItemStack.EMPTY);
return ItemStack.EMPTY;
}
if (index < 36) {
ItemStack stackToInsert = playerInventory.getStackInSlot(index);
ItemStack copy = stackToInsert.copy();
copy.setCount(1);
filterInventory.setStackInSlot(0, copy);
ghostInventory.setStackInSlot(0, copy);
}
return ItemStack.EMPTY;
}
@Override
protected int getInventoryOffset() {
protected int getPlayerInventoryXOffset() {
return 83;
}
@ -134,6 +134,7 @@ public class AttributeFilterContainer extends AbstractFilterContainer {
@Override
protected void saveData(ItemStack filterItem) {
super.saveData(filterItem);
filterItem.getOrCreateTag()
.putInt("WhitelistMode", whitelistMode.ordinal());
ListNBT attributes = new ListNBT();
@ -141,7 +142,8 @@ public class AttributeFilterContainer extends AbstractFilterContainer {
if (at == null)
return;
CompoundNBT compoundNBT = new CompoundNBT();
at.getFirst().serializeNBT(compoundNBT);
at.getFirst()
.serializeNBT(compoundNBT);
compoundNBT.putBoolean("Inverted", at.getSecond());
attributes.add(compoundNBT);
});

View file

@ -91,7 +91,7 @@ public class AttributeFilterScreen extends AbstractFilterScreen<AttributeFilterC
attributeSelector = new SelectionScrollInput(x + 39, y + 21, 137, 18);
attributeSelector.forOptions(Arrays.asList(StringTextComponent.EMPTY));
attributeSelector.removeCallback();
referenceItemChanged(container.filterInventory.getStackInSlot(0));
referenceItemChanged(container.ghostInventory.getStackInSlot(0));
widgets.add(attributeSelector);
widgets.add(attributeSelectorLabel);
@ -160,7 +160,7 @@ public class AttributeFilterScreen extends AbstractFilterScreen<AttributeFilterC
@Override
public void renderWindowForeground(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) {
ItemStack stack = container.filterInventory.getStackInSlot(1);
ItemStack stack = container.ghostInventory.getStackInSlot(1);
matrixStack.push();
matrixStack.translate(0.0F, 0.0F, 32.0F);
this.setZOffset(200);
@ -177,7 +177,7 @@ public class AttributeFilterScreen extends AbstractFilterScreen<AttributeFilterC
@Override
public void tick() {
super.tick();
ItemStack stackInSlot = container.filterInventory.getStackInSlot(0);
ItemStack stackInSlot = container.ghostInventory.getStackInSlot(0);
if (!stackInSlot.equals(lastItemScanned, false))
referenceItemChanged(stackInSlot);
}

View file

@ -31,19 +31,18 @@ public class FilterContainer extends AbstractFilterContainer {
protected void addFilterSlots() {
int x = -27;
int y = 20;
for (int row = 0; row < 2; ++row)
for (int col = 0; col < 9; ++col)
this.addSlot(new SlotItemHandler(filterInventory, col + row * 9, x + col * 18, y + row * 18));
this.addSlot(new SlotItemHandler(ghostInventory, col + row * 9, x + col * 18, y + row * 18));
}
@Override
protected ItemStackHandler createFilterInventory() {
return FilterItem.getFilterItems(filterItem);
protected ItemStackHandler createGhostInventory() {
return FilterItem.getFilterItems(contentHolder);
}
@Override
protected int getInventoryOffset() {
protected int getPlayerInventoryXOffset() {
return 97;
}
@ -56,6 +55,7 @@ public class FilterContainer extends AbstractFilterContainer {
@Override
protected void saveData(ItemStack filterItem) {
super.saveData(filterItem);
CompoundNBT tag = filterItem.getOrCreateTag();
tag.putBoolean("RespectNBT", respectNBT);
tag.putBoolean("Blacklist", blacklist);

View file

@ -57,7 +57,7 @@ public class FilterScreenPacket extends SimplePacketBase {
if (option == Option.IGNORE_DATA)
c.respectNBT = false;
if (option == Option.UPDATE_FILTER_ITEM)
c.filterInventory.setStackInSlot(
c.ghostInventory.setStackInSlot(
data.getInt("Slot"),
net.minecraft.item.ItemStack.read(data.getCompound("Item")));
}

View file

@ -24,6 +24,7 @@ import com.simibubi.create.content.contraptions.components.turntable.TurntableHa
import com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation;
import com.simibubi.create.content.contraptions.relays.belt.item.BeltConnectorHandler;
import com.simibubi.create.content.curiosities.armor.CopperBacktankArmorLayer;
import com.simibubi.create.content.curiosities.tools.BlueprintOverlayRenderer;
import com.simibubi.create.content.curiosities.tools.ExtendoGripRenderHandler;
import com.simibubi.create.content.curiosities.zapper.ZapperItem;
import com.simibubi.create.content.curiosities.zapper.ZapperRenderHandler;
@ -143,6 +144,7 @@ public class ClientEvents {
CreateClient.OUTLINER.tickOutlines();
CreateClient.GHOST_BLOCKS.tickGhosts();
ContraptionRenderDispatcher.tick();
BlueprintOverlayRenderer.tick();
}
@SubscribeEvent
@ -225,6 +227,7 @@ public class ClientEvents {
float partialTicks) {
CreateClient.SCHEMATIC_HANDLER.renderOverlay(ms, buffer, light, overlay, partialTicks);
LinkedControllerClientHandler.renderOverlay(ms, buffer, light, overlay, partialTicks);
BlueprintOverlayRenderer.renderOverlay(ms, buffer, light, overlay, partialTicks);
}
@SubscribeEvent

View file

@ -59,6 +59,7 @@ public enum AllGuiTextures implements IScreenRenderable {
SEQUENCER_AWAIT("sequencer.png", 0, 160, 162, 22),
LINKED_CONTROLLER("curiosities2.png", 180, 109),
BLUEPRINT("curiosities2.png", 0, 109, 179, 109),
// JEI
JEI_SLOT("jei/widgets.png", 18, 18),
@ -83,6 +84,11 @@ public enum AllGuiTextures implements IScreenRenderable {
INDICATOR_GREEN("widgets.png", 36, 18, 18, 6),
INDICATOR_YELLOW("widgets.png", 54, 18, 18, 6),
INDICATOR_RED("widgets.png", 72, 18, 18, 6),
HOTSLOT_ARROW("widgets.png", 24, 51, 20, 12),
HOTSLOT("widgets.png", 0, 68, 22, 22),
HOTSLOT_ACTIVE("widgets.png", 0, 46, 22, 22),
HOTSLOT_SUPER_ACTIVE("widgets.png", 27, 67, 24, 24),
SPEECH_TOOLTIP_BACKGROUND("widgets.png", 0, 24, 8, 8),
SPEECH_TOOLTIP_COLOR("widgets.png", 8, 24, 8, 8),

View file

@ -0,0 +1,149 @@
package com.simibubi.create.foundation.gui;
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.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.items.ItemHandlerHelper;
import net.minecraftforge.items.ItemStackHandler;
public abstract class GhostItemContainer<T> extends Container implements IClearableContainer {
public PlayerEntity player;
public PlayerInventory playerInventory;
public ItemStackHandler ghostInventory;
public T contentHolder;
protected GhostItemContainer(ContainerType<?> type, int id, PlayerInventory inv, PacketBuffer extraData) {
super(type, id);
init(inv, createOnClient(extraData));
}
protected GhostItemContainer(ContainerType<?> type, int id, PlayerInventory inv, T contentHolder) {
super(type, id);
init(inv, contentHolder);
}
@OnlyIn(Dist.CLIENT)
protected abstract T createOnClient(PacketBuffer extraData);
protected abstract void addSlots();
protected abstract ItemStackHandler createGhostInventory();
protected abstract void readData(T contentHolder);
protected abstract void saveData(T contentHolder);
protected abstract boolean allowRepeats();
protected void init(PlayerInventory inv, T contentHolder) {
player = inv.player;
playerInventory = inv;
this.contentHolder = contentHolder;
ghostInventory = createGhostInventory();
readData(contentHolder);
addSlots();
detectAndSendChanges();
}
@Override
public void clearContents() {
for (int i = 0; i < ghostInventory.getSlots(); i++)
ghostInventory.setStackInSlot(i, ItemStack.EMPTY);
}
protected void addPlayerSlots(int x, int y) {
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));
}
@Override
public boolean canMergeSlot(ItemStack stack, Slot slotIn) {
return slotIn.inventory == playerInventory;
}
@Override
public boolean canDragIntoSlot(Slot slotIn) {
if (allowRepeats())
return true;
return slotIn.inventory == playerInventory;
}
@Override
public boolean canInteractWith(PlayerEntity playerIn) {
return true;
}
@Override
public ItemStack slotClick(int slotId, int dragType, ClickType clickTypeIn, PlayerEntity player) {
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 = ghostInventory.getStackInSlot(slot)
.copy();
stackInSlot.setCount(stackInSlot.getMaxStackSize());
playerInventory.setItemStack(stackInSlot);
return ItemStack.EMPTY;
}
return ItemStack.EMPTY;
}
if (held.isEmpty()) {
ghostInventory.setStackInSlot(slot, ItemStack.EMPTY);
getSlot(slotId).onSlotChanged();
return ItemStack.EMPTY;
}
ItemStack insert = held.copy();
insert.setCount(1);
ghostInventory.setStackInSlot(slot, insert);
getSlot(slotId).onSlotChanged();
return held;
}
@Override
public ItemStack transferStackInSlot(PlayerEntity playerIn, int index) {
if (index < 36) {
ItemStack stackToInsert = playerInventory.getStackInSlot(index);
for (int i = 0; i < ghostInventory.getSlots(); i++) {
ItemStack stack = ghostInventory.getStackInSlot(i);
if (!allowRepeats() && ItemHandlerHelper.canItemStacksStack(stack, stackToInsert))
break;
if (stack.isEmpty()) {
ItemStack copy = stackToInsert.copy();
copy.setCount(1);
ghostInventory.insertItem(i, copy, false);
getSlot(i + 36).onSlotChanged();
break;
}
}
} else {
ghostInventory.extractItem(index - 36, 1, false);
getSlot(index).onSlotChanged();
}
return ItemStack.EMPTY;
}
@Override
public void onContainerClosed(PlayerEntity playerIn) {
super.onContainerClosed(playerIn);
saveData(contentHolder);
}
}

View file

@ -0,0 +1,53 @@
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.item.ItemStack;
import net.minecraft.network.PacketBuffer;
import net.minecraftforge.fml.network.NetworkEvent.Context;
public class GhostItemSubmitPacket extends SimplePacketBase {
private final ItemStack item;
private final int slot;
public GhostItemSubmitPacket(ItemStack item, int slot) {
this.item = item;
this.slot = slot;
}
public GhostItemSubmitPacket(PacketBuffer buffer) {
item = buffer.readItemStack();
slot = buffer.readInt();
}
@Override
public void write(PacketBuffer buffer) {
buffer.writeItemStack(item);
buffer.writeInt(slot);
}
@Override
public void handle(Supplier<Context> context) {
context.get()
.enqueueWork(() -> {
ServerPlayerEntity player = context.get()
.getSender();
if (player == null)
return;
if (player.openContainer instanceof GhostItemContainer) {
GhostItemContainer<?> c = (GhostItemContainer<?>) player.openContainer;
c.ghostInventory.setStackInSlot(slot, item);
c.getSlot(36 + slot).onSlotChanged();
}
});
context.get()
.setPacketHandled(true);
}
}

View file

@ -22,6 +22,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.tra
import com.simibubi.create.content.contraptions.fluids.actors.FluidSplashPacket;
import com.simibubi.create.content.contraptions.relays.advanced.sequencer.ConfigureSequencedGearshiftPacket;
import com.simibubi.create.content.curiosities.symmetry.SymmetryEffectPacket;
import com.simibubi.create.content.curiosities.tools.BlueprintAssignCompleteRecipePacket;
import com.simibubi.create.content.curiosities.tools.ExtendoGripInteractionPacket;
import com.simibubi.create.content.curiosities.zapper.ZapperBeamPacket;
import com.simibubi.create.content.logistics.block.depot.EjectorElytraPacket;
@ -44,6 +45,7 @@ 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.gui.GhostItemSubmitPacket;
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;
@ -88,6 +90,8 @@ public enum AllPackets {
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),
SUBMIT_GHOST_ITEM(GhostItemSubmitPacket.class, GhostItemSubmitPacket::new, PLAY_TO_SERVER),
BLUEPRINT_COMPLETE_RECIPE(BlueprintAssignCompleteRecipePacket.class, BlueprintAssignCompleteRecipePacket::new, PLAY_TO_SERVER),
// Server to Client
SYMMETRY_EFFECT(SymmetryEffectPacket.class, SymmetryEffectPacket::new, PLAY_TO_CLIENT),
@ -106,6 +110,7 @@ public enum AllPackets {
BLOCK_HIGHLIGHT(HighlightPacket.class, HighlightPacket::new, PLAY_TO_CLIENT),
TUNNEL_FLAP(TunnelFlapPacket.class, TunnelFlapPacket::new, PLAY_TO_CLIENT),
FUNNEL_FLAP(FunnelFlapPacket.class, FunnelFlapPacket::new, PLAY_TO_CLIENT),
PERSISTENT_DATA(ISyncPersistentData.Packet.class, ISyncPersistentData.Packet::new, PLAY_TO_CLIENT),
;

View file

@ -0,0 +1,64 @@
package com.simibubi.create.foundation.networking;
import java.util.Iterator;
import java.util.function.Supplier;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.Entity;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.network.PacketBuffer;
import net.minecraftforge.fml.network.NetworkEvent.Context;
import net.minecraftforge.fml.network.PacketDistributor;
public interface ISyncPersistentData {
void onPersistentDataUpdated();
default void syncPersistentDataWithTracking(Entity self) {
AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> self), new Packet(self));
}
public static class Packet extends SimplePacketBase {
private int entityId;
private Entity entity;
private CompoundNBT readData;
public Packet(Entity entity) {
this.entity = entity;
this.entityId = entity.getEntityId();
}
public Packet(PacketBuffer buffer) {
entityId = buffer.readInt();
readData = buffer.readCompoundTag();
}
@Override
public void write(PacketBuffer buffer) {
buffer.writeInt(entityId);
buffer.writeCompoundTag(entity.getPersistentData());
}
@Override
public void handle(Supplier<Context> context) {
context.get()
.enqueueWork(() -> {
Entity entityByID = Minecraft.getInstance().world.getEntityByID(entityId);
if (!(entityByID instanceof ISyncPersistentData))
return;
CompoundNBT data = entityByID.getPersistentData();
for (Iterator<String> iterator = data.keySet()
.iterator(); iterator.hasNext();) {
data.remove(iterator.next());
}
data.merge(readData);
((ISyncPersistentData) entityByID).onPersistentDataUpdated();
});
context.get()
.setPacketHandled(true);
}
}
}

View file

@ -470,6 +470,14 @@
"create.linked_controller.frequency_slot_1": "Keybind: %1$s, Freq. #1",
"create.linked_controller.frequency_slot_2": "Keybind: %1$s, Freq. #2",
"create.crafting_blueprint.crafting_slot": "Ingredient Slot",
"create.crafting_blueprint.filter_items_viable": "Advanced filter items are viable",
"create.crafting_blueprint.display_slot": "Display Slot",
"create.crafting_blueprint.inferred": "Inferred from recipe",
"create.crafting_blueprint.manually_assigned": "Manually assigned",
"create.crafting_blueprint.secondary_display_slot": "Secondary Display Slot",
"create.crafting_blueprint.optional": "Optional",
"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,21 @@
{
"credit": "Made with Blockbench",
"textures": {
"0": "create:entity/blueprint_large",
"particle": "create:entity/blueprint_large"
},
"elements": [
{
"from": [-16, 0, -16],
"to": [32, 1, 32],
"faces": {
"north": {"uv": [0, 0, 12, 0.25], "rotation": 180, "texture": "#0"},
"east": {"uv": [11.75, 0, 12, 12], "rotation": 90, "texture": "#0"},
"south": {"uv": [0, 11.75, 12, 12], "texture": "#0"},
"west": {"uv": [0, 0, 0.25, 12], "rotation": 270, "texture": "#0"},
"up": {"uv": [0, 0, 12, 12], "texture": "#0"},
"down": {"uv": [0, 0, 12, 12], "rotation": 270, "texture": "#0"}
}
}
]
}

View file

@ -0,0 +1,21 @@
{
"credit": "Made with Blockbench",
"textures": {
"0": "create:entity/blueprint_medium",
"particle": "create:entity/blueprint_medium"
},
"elements": [
{
"from": [-8, 0, -8],
"to": [24, 1, 24],
"faces": {
"north": {"uv": [0, 0, 16, 0.5], "rotation": 180, "texture": "#0"},
"east": {"uv": [0, 15.5, 16, 16], "rotation": 180, "texture": "#0"},
"south": {"uv": [0, 15.5, 16, 16], "texture": "#0"},
"west": {"uv": [0, 0, 0.5, 16], "rotation": 270, "texture": "#0"},
"up": {"uv": [0, 0, 16, 16], "texture": "#0"},
"down": {"uv": [0, 0, 16, 16], "rotation": 270, "texture": "#0"}
}
}
]
}

View file

@ -0,0 +1,21 @@
{
"credit": "Made with Blockbench",
"textures": {
"0": "create:entity/blueprint_small",
"particle": "create:entity/blueprint_small"
},
"elements": [
{
"from": [0, 0, 0],
"to": [16, 1, 16],
"faces": {
"north": {"uv": [0, 0, 16, 1], "rotation": 180, "texture": "#0"},
"east": {"uv": [0, 15, 16, 16], "rotation": 180, "texture": "#0"},
"south": {"uv": [0, 15, 16, 16], "texture": "#0"},
"west": {"uv": [0, 0, 1, 16], "rotation": 270, "texture": "#0"},
"up": {"uv": [0, 0, 16, 16], "texture": "#0"},
"down": {"uv": [0, 0, 16, 16], "rotation": 270, "texture": "#0"}
}
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 674 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 737 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 B