Basic Brewing

- Refactored JEI plugin to use a builder for categories
- The mixer can now process vanilla potion recipes
- JEI support for fluid potion mixing
- Refined some categories to not show obsolete information
- Compacting and automatic vanilla packing are now in separate tabs
- Fluids can now be manually picked up from a basin
- Basins and Spouts can now extract from and fill vanilla potion items
- Improved the filtering for fluid tests, such as the basin recipe and smart pipes
- Fixed CombinedTankWrapper losing nbt data of transferred fluidstacks
This commit is contained in:
simibubi 2020-10-19 22:07:05 +02:00
parent dd95096bfa
commit b7bed44a61
62 changed files with 1533 additions and 813 deletions

View file

@ -368,17 +368,17 @@ 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
ec6eb28b76106e24adb255e49943da3f53196bfb assets/create/lang/en_ud.json
f719ad41c8be237bbbafa8fabd8fda2b47288a31 assets/create/lang/en_us.json
5f8522c527cbbe50e33a7774316988fa6077d78d assets/create/lang/unfinished/de_de.json
0473893175500c6fd3f5410b575fc6ffc3abbb28 assets/create/lang/unfinished/fr_fr.json
c9fb5f2769f3e9be347bcd34b21a6c961e9a2324 assets/create/lang/unfinished/it_it.json
9bf0b4231a4f3d58b31fdb8d9876c8fdb40c5df5 assets/create/lang/unfinished/ja_jp.json
d7bd07920ecca15c2fe0728b141b3a9230ab545f assets/create/lang/unfinished/ko_kr.json
71c6d13fd8b300c851a591b76b32eff442acf586 assets/create/lang/unfinished/nl_nl.json
1668581de8b7ff54bb8cf2d705faa07936d2d8fd assets/create/lang/unfinished/pt_br.json
891d5a4abd250d7901a3a3df4907722e8ef864e9 assets/create/lang/unfinished/ru_ru.json
ef6159365f4746e8cc979527801893c92f19e6da assets/create/lang/unfinished/zh_cn.json
33f621fe1a09a46426af59c9352c33e97c2bc00d assets/create/lang/en_ud.json
f68da0c370026f416745b46445b53c63457cdeac assets/create/lang/en_us.json
1fa1a84b7dae8c7636a667e094883646ad6fa1e2 assets/create/lang/unfinished/de_de.json
4b2501a9d7730b4fb469d241afd72483171ce36b assets/create/lang/unfinished/fr_fr.json
efff9eee3f434fa04b3a688e8e861ab7d36fb45f assets/create/lang/unfinished/it_it.json
6db6ebd43ec38e11ad81f4b997b5765857bdf8da assets/create/lang/unfinished/ja_jp.json
3975b1184f38e7d7150ba2be0179bd3cf36ed7ca assets/create/lang/unfinished/ko_kr.json
84c44b3b4805925d0b489e295b38a72dbf2703e1 assets/create/lang/unfinished/nl_nl.json
f82f1e6250dd9a5ca9a7b92078bf1f7429d14d00 assets/create/lang/unfinished/pt_br.json
72d5dcbaa454de0ff33ff0cb2108938c2a5e677a assets/create/lang/unfinished/ru_ru.json
fdc2007ea9e3f8d8b2a6f8dedc434b591a0bbf0a assets/create/lang/unfinished/zh_cn.json
846200eb548d3bfa2e77b41039de159b4b6cfb45 assets/create/models/block/acacia_window.json
1930fa3a3c98d53dd19e4ee7f55bc27fd47aa281 assets/create/models/block/acacia_window_pane_noside.json
1763ea2c9b981d187f5031ba608f3d5d3be3986a assets/create/models/block/acacia_window_pane_noside_alt.json
@ -2723,7 +2723,6 @@ ddda28bb6efc43b7e3149756daf53e1664187283 data/create/recipes/dolomite_cobbleston
500ecdfdcf34e9d26256948e206aab4f0b79e659 data/create/recipes/dolomite_cobblestone_wall_from_dolomite_cobblestone_stonecutting.json
ff39e629b242ae91e23aec86b0a1f757dd938305 data/create/recipes/dolomite_pillar.json
b4a8d14d9a20e812e0acb691b5b511a87e8b0576 data/create/recipes/dolomite_pillar_from_dolomite_stonecutting.json
ae6698363e49f7cb5f2ed52c6b8805bebed31fa2 data/create/recipes/emptying/water_bottle.json
0e11aa1accb71ed62e212f23a7069b7b7b4e8119 data/create/recipes/fancy_andesite_bricks_from_andesite_stonecutting.json
8b86fc9a9416adeaab3f26192a73a481887675c3 data/create/recipes/fancy_andesite_bricks_slab.json
c7b762b25c7a6705dba3e922e981be851ac4f36b data/create/recipes/fancy_andesite_bricks_slab_from_fancy_andesite_bricks_stonecutting.json
@ -2787,7 +2786,6 @@ bd355332d17adcb0460b1d43146ca288efb78395 data/create/recipes/fancy_weathered_lim
d2ab9ce73636773165564506580f2ec13bd1fc50 data/create/recipes/fancy_weathered_limestone_bricks_stairs_from_fancy_weathered_limestone_bricks_stonecutting.json
36947f27d2b2e57b00440fd5acd06a7554e5a387 data/create/recipes/fancy_weathered_limestone_bricks_wall.json
1d0e41ca98e48073c72adf4077610c96e592f9a5 data/create/recipes/fancy_weathered_limestone_bricks_wall_from_fancy_weathered_limestone_bricks_stonecutting.json
3196d3eda9e67771e86e9af7026d4388765a8a73 data/create/recipes/filling/water_bottle.json
5b8bbde7f8b270ab75fac18d6858f2fadbc0efa3 data/create/recipes/framed_glass_from_glass_colorless_stonecutting.json
d697de0c9b706ca4e18da7a2d769e7e5fe8d769d data/create/recipes/framed_glass_pane.json
a0dae50faaa1b7142bb4309675e3084c68daa547 data/create/recipes/gabbro_bricks_from_gabbro_stonecutting.json
@ -2909,7 +2907,7 @@ e7bfaa806d57573d060fac0a5e7a84f345b8bb85 data/create/recipes/mixing/andesite_all
76939e4d3e5b615ae21d14c0ff7b917a622bcf80 data/create/recipes/mixing/chromatic_compound.json
d9a3dff1288d675ab812eef1eb73cb27dcc71bd2 data/create/recipes/mixing/crushed_brass.json
00b165ea38d834c7955440e87062004a8182c3f8 data/create/recipes/mixing/gunpowder.json
743c2d62c94a4989b88046c9cdf0fa024cd09fa8 data/create/recipes/mixing/temp_cobble.json
cf2a741be46fd2069f242afe74eb7c11f3139c46 data/create/recipes/mixing/temp_cobble.json
3295a2195707f952a83deb3bed10b43570b215e5 data/create/recipes/mixing/temp_lava.json
1998c6f84f871d6da58ec29d729401d18f8f1aa1 data/create/recipes/mossy_andesite_from_andesite_stonecutting.json
89929d9cb11b5c589b2ecfa821c61add1ef7b62b data/create/recipes/mossy_dark_scoria_from_dark_scoria_stonecutting.json

View file

@ -373,6 +373,7 @@
"entity.create.seat": "\u0287\u0250\u01DDS",
"entity.create.stationary_contraption": "uo\u0131\u0287d\u0250\u0279\u0287uo\u0186 \u028E\u0279\u0250uo\u0131\u0287\u0250\u0287S",
"entity.create.super_glue": "\u01DDn\u05DF\u2141 \u0279\u01DDdnS",
"fluid.create.flowing_potion": "uo\u0131\u0287o\u0500",
"item.create.andesite_alloy": "\u028Eo\u05DF\u05DF\u2C6F \u01DD\u0287\u0131s\u01DDpu\u2C6F",
"item.create.attribute_filter": "\u0279\u01DD\u0287\u05DF\u0131\u2132 \u01DD\u0287nq\u0131\u0279\u0287\u0287\u2C6F",
"item.create.belt_connector": "\u0287\u05DF\u01DD\u15FA \u05DF\u0250\u0254\u0131u\u0250\u0265\u0254\u01DDW",

View file

@ -378,6 +378,8 @@
"entity.create.stationary_contraption": "Stationary Contraption",
"entity.create.super_glue": "Super Glue",
"fluid.create.flowing_potion": "Potion",
"item.create.andesite_alloy": "Andesite Alloy",
"item.create.attribute_filter": "Attribute Filter",
"item.create.belt_connector": "Mechanical Belt",
@ -540,26 +542,26 @@
"create.recipe.crushing": "Crushing",
"create.recipe.milling": "Milling",
"create.recipe.splashing": "Bulk Washing",
"create.recipe.splashing.fan": "Fan behind Flowing Water",
"create.recipe.smoking_via_fan": "Bulk Smoking",
"create.recipe.smoking_via_fan.fan": "Fan behind Fire",
"create.recipe.blasting_via_fan": "Bulk Smelting",
"create.recipe.blasting_via_fan.fan": "Fan behind Lava",
"create.recipe.fan_washing": "Bulk Washing",
"create.recipe.fan_washing.fan": "Fan behind Flowing Water",
"create.recipe.fan_smoking": "Bulk Smoking",
"create.recipe.fan_smoking.fan": "Fan behind Fire",
"create.recipe.fan_blasting": "Bulk Blasting",
"create.recipe.fan_blasting.fan": "Fan behind Lava",
"create.recipe.pressing": "Pressing",
"create.recipe.mixing": "Mixing",
"create.recipe.shapeless_mixing": "Shapeless Crafting",
"create.recipe.automatic_shapeless": "Automated Shapeless Crafting",
"create.recipe.automatic_brewing": "Automated Brewing",
"create.recipe.packing": "Compacting",
"create.recipe.automatic_packing": "Automated Packing",
"create.recipe.sawing": "Sawing",
"create.recipe.mechanical_crafting": "Crafting",
"create.recipe.mechanical_crafting_exclusive": "Mechanical Crafting",
"create.recipe.mechanical_crafting": "Mechanical Crafting",
"create.recipe.automatic_shaped": "Automated Shaped Crafting",
"create.recipe.block_cutting": "Block Cutting",
"create.recipe.blockzapper_upgrade": "Handheld Blockzapper",
"create.recipe.sandpaper_polishing": "Sandpaper Polishing",
"create.recipe.mystery_conversion": "Chromatic Metamorphosis",
"create.recipe.processing.catalyst": "Catalyst",
"create.recipe.mystery_conversion": "Mysterious Conversion",
"create.recipe.processing.chance": "%1$s%% Chance",
"create.recipe.processing.chanceToReturn": "%1$s%% Chance to Return",
"create.recipe.heat_requirement.none": "No Heating Required",
"create.recipe.heat_requirement.heated": "Heated",
"create.recipe.heat_requirement.superheated": "Super-Heated",
@ -577,7 +579,6 @@
"create.generic.unit.rpm": "RPM",
"create.generic.unit.stress": "su",
"create.generic.unit.degrees": "°",
"create.generic.unit.bucket": "1 Bucket",
"create.generic.unit.millibuckets": "%1$smB",
"create.action.scroll": "Scroll",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 922",
"_": "Missing Localizations: 928",
"_": "->------------------------] Game Elements [------------------------<-",
@ -379,6 +379,8 @@
"entity.create.stationary_contraption": "UNLOCALIZED: Stationary Contraption",
"entity.create.super_glue": "UNLOCALIZED: Super Glue",
"fluid.create.flowing_potion": "UNLOCALIZED: Potion",
"item.create.andesite_alloy": "UNLOCALIZED: Andesite Alloy",
"item.create.attribute_filter": "UNLOCALIZED: Attribute Filter",
"item.create.belt_connector": "Mechanischer Riemen",
@ -541,26 +543,26 @@
"create.recipe.crushing": "Mahlen",
"create.recipe.milling": "UNLOCALIZED: Milling",
"create.recipe.splashing": "Waschen",
"create.recipe.splashing.fan": "Propeller hinter fließendem Wasser",
"create.recipe.smoking_via_fan": "Räuchern",
"create.recipe.smoking_via_fan.fan": "Propeller hinter Feuer",
"create.recipe.blasting_via_fan": "Schmelzen",
"create.recipe.blasting_via_fan.fan": "Propeller hinter Lava",
"create.recipe.fan_washing": "UNLOCALIZED: Bulk Washing",
"create.recipe.fan_washing.fan": "UNLOCALIZED: Fan behind Flowing Water",
"create.recipe.fan_smoking": "UNLOCALIZED: Bulk Smoking",
"create.recipe.fan_smoking.fan": "UNLOCALIZED: Fan behind Fire",
"create.recipe.fan_blasting": "UNLOCALIZED: Bulk Blasting",
"create.recipe.fan_blasting.fan": "UNLOCALIZED: Fan behind Lava",
"create.recipe.pressing": "Mechanische Presse",
"create.recipe.mixing": "UNLOCALIZED: Mixing",
"create.recipe.shapeless_mixing": "UNLOCALIZED: Shapeless Crafting",
"create.recipe.automatic_shapeless": "UNLOCALIZED: Automated Shapeless Crafting",
"create.recipe.automatic_brewing": "UNLOCALIZED: Automated Brewing",
"create.recipe.packing": "UNLOCALIZED: Compacting",
"create.recipe.automatic_packing": "UNLOCALIZED: Automated Packing",
"create.recipe.sawing": "UNLOCALIZED: Sawing",
"create.recipe.mechanical_crafting": "UNLOCALIZED: Crafting",
"create.recipe.mechanical_crafting_exclusive": "UNLOCALIZED: Mechanical Crafting",
"create.recipe.mechanical_crafting": "UNLOCALIZED: Mechanical Crafting",
"create.recipe.automatic_shaped": "UNLOCALIZED: Automated Shaped Crafting",
"create.recipe.block_cutting": "UNLOCALIZED: Block Cutting",
"create.recipe.blockzapper_upgrade": "Blockpistole",
"create.recipe.sandpaper_polishing": "UNLOCALIZED: Sandpaper Polishing",
"create.recipe.mystery_conversion": "UNLOCALIZED: Chromatic Metamorphosis",
"create.recipe.processing.catalyst": "UNLOCALIZED: Catalyst",
"create.recipe.mystery_conversion": "UNLOCALIZED: Mysterious Conversion",
"create.recipe.processing.chance": "Chance: %1$s%%",
"create.recipe.processing.chanceToReturn": "UNLOCALIZED: %1$s%% Chance to Return",
"create.recipe.heat_requirement.none": "UNLOCALIZED: No Heating Required",
"create.recipe.heat_requirement.heated": "UNLOCALIZED: Heated",
"create.recipe.heat_requirement.superheated": "UNLOCALIZED: Super-Heated",
@ -578,7 +580,6 @@
"create.generic.unit.rpm": "UNLOCALIZED: RPM",
"create.generic.unit.stress": "UNLOCALIZED: su",
"create.generic.unit.degrees": "UNLOCALIZED: °",
"create.generic.unit.bucket": "UNLOCALIZED: 1 Bucket",
"create.generic.unit.millibuckets": "UNLOCALIZED: %1$smB",
"create.action.scroll": "Wechseln",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 547",
"_": "Missing Localizations: 555",
"_": "->------------------------] Game Elements [------------------------<-",
@ -379,6 +379,8 @@
"entity.create.stationary_contraption": "UNLOCALIZED: Stationary Contraption",
"entity.create.super_glue": "UNLOCALIZED: Super Glue",
"fluid.create.flowing_potion": "UNLOCALIZED: Potion",
"item.create.andesite_alloy": "Alliage d'andésite",
"item.create.attribute_filter": "Filtre d'attribut",
"item.create.belt_connector": "Tapis roulant",
@ -541,26 +543,26 @@
"create.recipe.crushing": "Ecrasement",
"create.recipe.milling": "UNLOCALIZED: Milling",
"create.recipe.splashing": "Lavage en vrac",
"create.recipe.splashing.fan": "Ventilateur derrière de l'eau qui coule",
"create.recipe.smoking_via_fan": "Fumer en vrac",
"create.recipe.smoking_via_fan.fan": "Fan behind Fire",
"create.recipe.blasting_via_fan": "Ventilateur derrière du feu",
"create.recipe.blasting_via_fan.fan": "Ventilateur derrière de la lave",
"create.recipe.fan_washing": "UNLOCALIZED: Bulk Washing",
"create.recipe.fan_washing.fan": "UNLOCALIZED: Fan behind Flowing Water",
"create.recipe.fan_smoking": "UNLOCALIZED: Bulk Smoking",
"create.recipe.fan_smoking.fan": "UNLOCALIZED: Fan behind Fire",
"create.recipe.fan_blasting": "UNLOCALIZED: Bulk Blasting",
"create.recipe.fan_blasting.fan": "UNLOCALIZED: Fan behind Lava",
"create.recipe.pressing": "Pressage",
"create.recipe.mixing": "Mixage",
"create.recipe.shapeless_mixing": "UNLOCALIZED: Shapeless Crafting",
"create.recipe.automatic_shapeless": "UNLOCALIZED: Automated Shapeless Crafting",
"create.recipe.automatic_brewing": "UNLOCALIZED: Automated Brewing",
"create.recipe.packing": "Compactage",
"create.recipe.automatic_packing": "UNLOCALIZED: Automated Packing",
"create.recipe.sawing": "UNLOCALIZED: Sawing",
"create.recipe.mechanical_crafting": "Fabrication mécanique",
"create.recipe.mechanical_crafting_exclusive": "UNLOCALIZED: Mechanical Crafting",
"create.recipe.automatic_shaped": "UNLOCALIZED: Automated Shaped Crafting",
"create.recipe.block_cutting": "Coupe de bloc",
"create.recipe.blockzapper_upgrade": "Blockzappeur portable",
"create.recipe.sandpaper_polishing": "Polissage au papier de verre",
"create.recipe.mystery_conversion": "Métamorphose chromatique",
"create.recipe.processing.catalyst": "Catalyseur",
"create.recipe.processing.chance": "%1$s%% de chance",
"create.recipe.processing.chanceToReturn": "%1$s%% de chance de retour",
"create.recipe.heat_requirement.none": "UNLOCALIZED: No Heating Required",
"create.recipe.heat_requirement.heated": "UNLOCALIZED: Heated",
"create.recipe.heat_requirement.superheated": "UNLOCALIZED: Super-Heated",
@ -578,7 +580,6 @@
"create.generic.unit.rpm": "tr/min",
"create.generic.unit.stress": "us",
"create.generic.unit.degrees": "°",
"create.generic.unit.bucket": "UNLOCALIZED: 1 Bucket",
"create.generic.unit.millibuckets": "UNLOCALIZED: %1$smB",
"create.action.scroll": "Faire défiler",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 535",
"_": "Missing Localizations: 539",
"_": "->------------------------] Game Elements [------------------------<-",
@ -379,6 +379,8 @@
"entity.create.stationary_contraption": "UNLOCALIZED: Stationary Contraption",
"entity.create.super_glue": "UNLOCALIZED: Super Glue",
"fluid.create.flowing_potion": "UNLOCALIZED: Potion",
"item.create.andesite_alloy": "Lega di Andesite",
"item.create.attribute_filter": "Filtro Attributi",
"item.create.belt_connector": "Nastro Meccanico",
@ -541,26 +543,26 @@
"create.recipe.crushing": "Frantumazione",
"create.recipe.milling": "Fresatura",
"create.recipe.splashing": "Lavaggio alla Rinfusa",
"create.recipe.splashing.fan": "Ventilatore Dietro l'Acqua Corrente",
"create.recipe.smoking_via_fan": "UNLOCALIZED: Bulk Smoking",
"create.recipe.smoking_via_fan.fan": "UNLOCALIZED: Fan behind Fire",
"create.recipe.blasting_via_fan": "UNLOCALIZED: Bulk Smelting",
"create.recipe.blasting_via_fan.fan": "UNLOCALIZED: Fan behind Lava",
"create.recipe.fan_washing": "UNLOCALIZED: Bulk Washing",
"create.recipe.fan_washing.fan": "UNLOCALIZED: Fan behind Flowing Water",
"create.recipe.fan_smoking": "UNLOCALIZED: Bulk Smoking",
"create.recipe.fan_smoking.fan": "UNLOCALIZED: Fan behind Fire",
"create.recipe.fan_blasting": "UNLOCALIZED: Bulk Blasting",
"create.recipe.fan_blasting.fan": "UNLOCALIZED: Fan behind Lava",
"create.recipe.pressing": "Pressatura",
"create.recipe.mixing": "Mescolamento",
"create.recipe.shapeless_mixing": "UNLOCALIZED: Shapeless Crafting",
"create.recipe.automatic_shapeless": "UNLOCALIZED: Automated Shapeless Crafting",
"create.recipe.automatic_brewing": "UNLOCALIZED: Automated Brewing",
"create.recipe.packing": "Compattazione",
"create.recipe.automatic_packing": "UNLOCALIZED: Automated Packing",
"create.recipe.sawing": "UNLOCALIZED: Sawing",
"create.recipe.mechanical_crafting": "Creazione Meccanico",
"create.recipe.mechanical_crafting_exclusive": "UNLOCALIZED: Mechanical Crafting",
"create.recipe.automatic_shaped": "UNLOCALIZED: Automated Shaped Crafting",
"create.recipe.block_cutting": "Taglio Blocco",
"create.recipe.blockzapper_upgrade": "UNLOCALIZED: Handheld Blockzapper",
"create.recipe.sandpaper_polishing": "Carta Vetrata Levigata",
"create.recipe.mystery_conversion": "Metamorfosi Cromatica",
"create.recipe.processing.catalyst": "Catalizzatore",
"create.recipe.processing.chance": "%1$s%% Possibilità",
"create.recipe.processing.chanceToReturn": "%1$s%% Possibilità di Ritorno",
"create.recipe.heat_requirement.none": "UNLOCALIZED: No Heating Required",
"create.recipe.heat_requirement.heated": "UNLOCALIZED: Heated",
"create.recipe.heat_requirement.superheated": "UNLOCALIZED: Super-Heated",
@ -578,7 +580,6 @@
"create.generic.unit.rpm": "RPM",
"create.generic.unit.stress": "su",
"create.generic.unit.degrees": "°",
"create.generic.unit.bucket": "UNLOCALIZED: 1 Bucket",
"create.generic.unit.millibuckets": "UNLOCALIZED: %1$smB",
"create.action.scroll": "Scorri",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 530",
"_": "Missing Localizations: 538",
"_": "->------------------------] Game Elements [------------------------<-",
@ -379,6 +379,8 @@
"entity.create.stationary_contraption": "UNLOCALIZED: Stationary Contraption",
"entity.create.super_glue": "UNLOCALIZED: Super Glue",
"fluid.create.flowing_potion": "UNLOCALIZED: Potion",
"item.create.andesite_alloy": "安山岩合金",
"item.create.attribute_filter": "属性フィルター",
"item.create.belt_connector": "メカニカルベルト",
@ -541,26 +543,26 @@
"create.recipe.crushing": "粉砕",
"create.recipe.milling": "製粉",
"create.recipe.splashing": "一括洗浄",
"create.recipe.splashing.fan": "流れる水の後ろにファンを置く",
"create.recipe.smoking_via_fan": "一括燻製",
"create.recipe.smoking_via_fan.fan": "炎の後ろにファンを置く",
"create.recipe.blasting_via_fan": "一括製錬",
"create.recipe.blasting_via_fan.fan": "溶岩の後ろにファンを置く",
"create.recipe.fan_washing": "UNLOCALIZED: Bulk Washing",
"create.recipe.fan_washing.fan": "UNLOCALIZED: Fan behind Flowing Water",
"create.recipe.fan_smoking": "UNLOCALIZED: Bulk Smoking",
"create.recipe.fan_smoking.fan": "UNLOCALIZED: Fan behind Fire",
"create.recipe.fan_blasting": "UNLOCALIZED: Bulk Blasting",
"create.recipe.fan_blasting.fan": "UNLOCALIZED: Fan behind Lava",
"create.recipe.pressing": "押しつぶし",
"create.recipe.mixing": "混合",
"create.recipe.shapeless_mixing": "UNLOCALIZED: Shapeless Crafting",
"create.recipe.automatic_shapeless": "UNLOCALIZED: Automated Shapeless Crafting",
"create.recipe.automatic_brewing": "UNLOCALIZED: Automated Brewing",
"create.recipe.packing": "圧縮",
"create.recipe.automatic_packing": "UNLOCALIZED: Automated Packing",
"create.recipe.sawing": "UNLOCALIZED: Sawing",
"create.recipe.mechanical_crafting": "メカニカルクラフト",
"create.recipe.mechanical_crafting_exclusive": "UNLOCALIZED: Mechanical Crafting",
"create.recipe.automatic_shaped": "UNLOCALIZED: Automated Shaped Crafting",
"create.recipe.block_cutting": "ブロックカット",
"create.recipe.blockzapper_upgrade": "携帯型ブロックザッパー",
"create.recipe.sandpaper_polishing": "紙やすりでの研磨",
"create.recipe.mystery_conversion": "色彩変態",
"create.recipe.processing.catalyst": "触媒",
"create.recipe.processing.chance": "%1$s%%チャンス",
"create.recipe.processing.chanceToReturn": "%1$s%%チャンスで戻る",
"create.recipe.heat_requirement.none": "UNLOCALIZED: No Heating Required",
"create.recipe.heat_requirement.heated": "UNLOCALIZED: Heated",
"create.recipe.heat_requirement.superheated": "UNLOCALIZED: Super-Heated",
@ -578,7 +580,6 @@
"create.generic.unit.rpm": "RPM",
"create.generic.unit.stress": "su",
"create.generic.unit.degrees": "°",
"create.generic.unit.bucket": "UNLOCALIZED: 1 Bucket",
"create.generic.unit.millibuckets": "UNLOCALIZED: %1$smB",
"create.action.scroll": "スクロール",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 535",
"_": "Missing Localizations: 539",
"_": "->------------------------] Game Elements [------------------------<-",
@ -379,6 +379,8 @@
"entity.create.stationary_contraption": "UNLOCALIZED: Stationary Contraption",
"entity.create.super_glue": "UNLOCALIZED: Super Glue",
"fluid.create.flowing_potion": "UNLOCALIZED: Potion",
"item.create.andesite_alloy": "안산암 합금",
"item.create.attribute_filter": "속성 필터 틀",
"item.create.belt_connector": "기계식 벨트",
@ -541,26 +543,26 @@
"create.recipe.crushing": "분쇄",
"create.recipe.milling": "맷돌질",
"create.recipe.splashing": "세척",
"create.recipe.splashing.fan": "물과 환풍기",
"create.recipe.smoking_via_fan": "UNLOCALIZED: Bulk Smoking",
"create.recipe.smoking_via_fan.fan": "UNLOCALIZED: Fan behind Fire",
"create.recipe.blasting_via_fan": "UNLOCALIZED: Bulk Smelting",
"create.recipe.blasting_via_fan.fan": "UNLOCALIZED: Fan behind Lava",
"create.recipe.fan_washing": "UNLOCALIZED: Bulk Washing",
"create.recipe.fan_washing.fan": "UNLOCALIZED: Fan behind Flowing Water",
"create.recipe.fan_smoking": "UNLOCALIZED: Bulk Smoking",
"create.recipe.fan_smoking.fan": "UNLOCALIZED: Fan behind Fire",
"create.recipe.fan_blasting": "UNLOCALIZED: Bulk Blasting",
"create.recipe.fan_blasting.fan": "UNLOCALIZED: Fan behind Lava",
"create.recipe.pressing": "압착",
"create.recipe.mixing": "혼합",
"create.recipe.shapeless_mixing": "UNLOCALIZED: Shapeless Crafting",
"create.recipe.automatic_shapeless": "UNLOCALIZED: Automated Shapeless Crafting",
"create.recipe.automatic_brewing": "UNLOCALIZED: Automated Brewing",
"create.recipe.packing": "압축",
"create.recipe.automatic_packing": "UNLOCALIZED: Automated Packing",
"create.recipe.sawing": "UNLOCALIZED: Sawing",
"create.recipe.mechanical_crafting": "기계 조합",
"create.recipe.mechanical_crafting_exclusive": "UNLOCALIZED: Mechanical Crafting",
"create.recipe.automatic_shaped": "UNLOCALIZED: Automated Shaped Crafting",
"create.recipe.block_cutting": "블럭 절단",
"create.recipe.blockzapper_upgrade": "UNLOCALIZED: Handheld Blockzapper",
"create.recipe.sandpaper_polishing": "사포 연마",
"create.recipe.mystery_conversion": "?",
"create.recipe.processing.catalyst": "촉매",
"create.recipe.processing.chance": "%1$s%% 확률",
"create.recipe.processing.chanceToReturn": "%1$s%% 확률로 반환",
"create.recipe.heat_requirement.none": "UNLOCALIZED: No Heating Required",
"create.recipe.heat_requirement.heated": "UNLOCALIZED: Heated",
"create.recipe.heat_requirement.superheated": "UNLOCALIZED: Super-Heated",
@ -578,7 +580,6 @@
"create.generic.unit.rpm": "RPM",
"create.generic.unit.stress": "su",
"create.generic.unit.degrees": "°",
"create.generic.unit.bucket": "UNLOCALIZED: 1 Bucket",
"create.generic.unit.millibuckets": "UNLOCALIZED: %1$smB",
"create.action.scroll": "스크롤하세요",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 861",
"_": "Missing Localizations: 867",
"_": "->------------------------] Game Elements [------------------------<-",
@ -379,6 +379,8 @@
"entity.create.stationary_contraption": "UNLOCALIZED: Stationary Contraption",
"entity.create.super_glue": "UNLOCALIZED: Super Glue",
"fluid.create.flowing_potion": "UNLOCALIZED: Potion",
"item.create.andesite_alloy": "UNLOCALIZED: Andesite Alloy",
"item.create.attribute_filter": "UNLOCALIZED: Attribute Filter",
"item.create.belt_connector": "Mechanische Transportband",
@ -541,26 +543,26 @@
"create.recipe.crushing": "Verpulveren",
"create.recipe.milling": "UNLOCALIZED: Milling",
"create.recipe.splashing": "Bulk Wassen",
"create.recipe.splashing.fan": "Ventilator achter vloeiend water",
"create.recipe.smoking_via_fan": "Bulk Rook",
"create.recipe.smoking_via_fan.fan": "Ventilator achter vuur",
"create.recipe.blasting_via_fan": "Bulk Smelten",
"create.recipe.blasting_via_fan.fan": "Ventilator achter Lava",
"create.recipe.fan_washing": "UNLOCALIZED: Bulk Washing",
"create.recipe.fan_washing.fan": "UNLOCALIZED: Fan behind Flowing Water",
"create.recipe.fan_smoking": "UNLOCALIZED: Bulk Smoking",
"create.recipe.fan_smoking.fan": "UNLOCALIZED: Fan behind Fire",
"create.recipe.fan_blasting": "UNLOCALIZED: Bulk Blasting",
"create.recipe.fan_blasting.fan": "UNLOCALIZED: Fan behind Lava",
"create.recipe.pressing": "Persen",
"create.recipe.mixing": "Mengen",
"create.recipe.shapeless_mixing": "UNLOCALIZED: Shapeless Crafting",
"create.recipe.automatic_shapeless": "UNLOCALIZED: Automated Shapeless Crafting",
"create.recipe.automatic_brewing": "UNLOCALIZED: Automated Brewing",
"create.recipe.packing": "Compressen",
"create.recipe.automatic_packing": "UNLOCALIZED: Automated Packing",
"create.recipe.sawing": "UNLOCALIZED: Sawing",
"create.recipe.mechanical_crafting": "UNLOCALIZED: Crafting",
"create.recipe.mechanical_crafting_exclusive": "UNLOCALIZED: Mechanical Crafting",
"create.recipe.mechanical_crafting": "UNLOCALIZED: Mechanical Crafting",
"create.recipe.automatic_shaped": "UNLOCALIZED: Automated Shaped Crafting",
"create.recipe.block_cutting": "Blok Zagen",
"create.recipe.blockzapper_upgrade": "Blokzapper",
"create.recipe.sandpaper_polishing": "UNLOCALIZED: Sandpaper Polishing",
"create.recipe.mystery_conversion": "UNLOCALIZED: Chromatic Metamorphosis",
"create.recipe.processing.catalyst": "UNLOCALIZED: Catalyst",
"create.recipe.mystery_conversion": "UNLOCALIZED: Mysterious Conversion",
"create.recipe.processing.chance": "%1$s%% Kans",
"create.recipe.processing.chanceToReturn": "UNLOCALIZED: %1$s%% Chance to Return",
"create.recipe.heat_requirement.none": "UNLOCALIZED: No Heating Required",
"create.recipe.heat_requirement.heated": "UNLOCALIZED: Heated",
"create.recipe.heat_requirement.superheated": "UNLOCALIZED: Super-Heated",
@ -578,7 +580,6 @@
"create.generic.unit.rpm": "UNLOCALIZED: RPM",
"create.generic.unit.stress": "UNLOCALIZED: su",
"create.generic.unit.degrees": "UNLOCALIZED: °",
"create.generic.unit.bucket": "UNLOCALIZED: 1 Bucket",
"create.generic.unit.millibuckets": "UNLOCALIZED: %1$smB",
"create.action.scroll": "Scroll",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 929",
"_": "Missing Localizations: 935",
"_": "->------------------------] Game Elements [------------------------<-",
@ -379,6 +379,8 @@
"entity.create.stationary_contraption": "UNLOCALIZED: Stationary Contraption",
"entity.create.super_glue": "UNLOCALIZED: Super Glue",
"fluid.create.flowing_potion": "UNLOCALIZED: Potion",
"item.create.andesite_alloy": "UNLOCALIZED: Andesite Alloy",
"item.create.attribute_filter": "UNLOCALIZED: Attribute Filter",
"item.create.belt_connector": "Esteira Mecânica",
@ -541,26 +543,26 @@
"create.recipe.crushing": "Moendo",
"create.recipe.milling": "UNLOCALIZED: Milling",
"create.recipe.splashing": "Lavando em Massa",
"create.recipe.splashing.fan": "Ventilador atras de Água corrente",
"create.recipe.smoking_via_fan": "Fumaceando em Massa",
"create.recipe.smoking_via_fan.fan": "Ventilador atras de Fogo",
"create.recipe.blasting_via_fan": "Fundindo em Massa",
"create.recipe.blasting_via_fan.fan": "Ventilador atras de Lava",
"create.recipe.fan_washing": "UNLOCALIZED: Bulk Washing",
"create.recipe.fan_washing.fan": "UNLOCALIZED: Fan behind Flowing Water",
"create.recipe.fan_smoking": "UNLOCALIZED: Bulk Smoking",
"create.recipe.fan_smoking.fan": "UNLOCALIZED: Fan behind Fire",
"create.recipe.fan_blasting": "UNLOCALIZED: Bulk Blasting",
"create.recipe.fan_blasting.fan": "UNLOCALIZED: Fan behind Lava",
"create.recipe.pressing": "Prensa Mecânica",
"create.recipe.mixing": "UNLOCALIZED: Mixing",
"create.recipe.shapeless_mixing": "UNLOCALIZED: Shapeless Crafting",
"create.recipe.automatic_shapeless": "UNLOCALIZED: Automated Shapeless Crafting",
"create.recipe.automatic_brewing": "UNLOCALIZED: Automated Brewing",
"create.recipe.packing": "UNLOCALIZED: Compacting",
"create.recipe.automatic_packing": "UNLOCALIZED: Automated Packing",
"create.recipe.sawing": "UNLOCALIZED: Sawing",
"create.recipe.mechanical_crafting": "UNLOCALIZED: Crafting",
"create.recipe.mechanical_crafting_exclusive": "UNLOCALIZED: Mechanical Crafting",
"create.recipe.mechanical_crafting": "UNLOCALIZED: Mechanical Crafting",
"create.recipe.automatic_shaped": "UNLOCALIZED: Automated Shaped Crafting",
"create.recipe.block_cutting": "UNLOCALIZED: Block Cutting",
"create.recipe.blockzapper_upgrade": "Blockzapper Portátil",
"create.recipe.sandpaper_polishing": "UNLOCALIZED: Sandpaper Polishing",
"create.recipe.mystery_conversion": "UNLOCALIZED: Chromatic Metamorphosis",
"create.recipe.processing.catalyst": "UNLOCALIZED: Catalyst",
"create.recipe.mystery_conversion": "UNLOCALIZED: Mysterious Conversion",
"create.recipe.processing.chance": "%1$s%% de chance",
"create.recipe.processing.chanceToReturn": "UNLOCALIZED: %1$s%% Chance to Return",
"create.recipe.heat_requirement.none": "UNLOCALIZED: No Heating Required",
"create.recipe.heat_requirement.heated": "UNLOCALIZED: Heated",
"create.recipe.heat_requirement.superheated": "UNLOCALIZED: Super-Heated",
@ -578,7 +580,6 @@
"create.generic.unit.rpm": "UNLOCALIZED: RPM",
"create.generic.unit.stress": "UNLOCALIZED: su",
"create.generic.unit.degrees": "UNLOCALIZED: °",
"create.generic.unit.bucket": "UNLOCALIZED: 1 Bucket",
"create.generic.unit.millibuckets": "UNLOCALIZED: %1$smB",
"create.action.scroll": "Rolar",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 923",
"_": "Missing Localizations: 929",
"_": "->------------------------] Game Elements [------------------------<-",
@ -379,6 +379,8 @@
"entity.create.stationary_contraption": "UNLOCALIZED: Stationary Contraption",
"entity.create.super_glue": "UNLOCALIZED: Super Glue",
"fluid.create.flowing_potion": "UNLOCALIZED: Potion",
"item.create.andesite_alloy": "UNLOCALIZED: Andesite Alloy",
"item.create.attribute_filter": "UNLOCALIZED: Attribute Filter",
"item.create.belt_connector": "Механическая лента",
@ -541,26 +543,26 @@
"create.recipe.crushing": "Дробление",
"create.recipe.milling": "UNLOCALIZED: Milling",
"create.recipe.splashing": "Промывка вентилятором",
"create.recipe.splashing.fan": "Вентилятор за проточной водой",
"create.recipe.smoking_via_fan": "Копчение вентилятором",
"create.recipe.smoking_via_fan.fan": "Вентилятор за огнём",
"create.recipe.blasting_via_fan": "Плавление вентилятором",
"create.recipe.blasting_via_fan.fan": "Вентелятор за лавой",
"create.recipe.fan_washing": "UNLOCALIZED: Bulk Washing",
"create.recipe.fan_washing.fan": "UNLOCALIZED: Fan behind Flowing Water",
"create.recipe.fan_smoking": "UNLOCALIZED: Bulk Smoking",
"create.recipe.fan_smoking.fan": "UNLOCALIZED: Fan behind Fire",
"create.recipe.fan_blasting": "UNLOCALIZED: Bulk Blasting",
"create.recipe.fan_blasting.fan": "UNLOCALIZED: Fan behind Lava",
"create.recipe.pressing": "Механический пресс",
"create.recipe.mixing": "UNLOCALIZED: Mixing",
"create.recipe.shapeless_mixing": "UNLOCALIZED: Shapeless Crafting",
"create.recipe.automatic_shapeless": "UNLOCALIZED: Automated Shapeless Crafting",
"create.recipe.automatic_brewing": "UNLOCALIZED: Automated Brewing",
"create.recipe.packing": "UNLOCALIZED: Compacting",
"create.recipe.automatic_packing": "UNLOCALIZED: Automated Packing",
"create.recipe.sawing": "UNLOCALIZED: Sawing",
"create.recipe.mechanical_crafting": "UNLOCALIZED: Crafting",
"create.recipe.mechanical_crafting_exclusive": "UNLOCALIZED: Mechanical Crafting",
"create.recipe.mechanical_crafting": "UNLOCALIZED: Mechanical Crafting",
"create.recipe.automatic_shaped": "UNLOCALIZED: Automated Shaped Crafting",
"create.recipe.block_cutting": "UNLOCALIZED: Block Cutting",
"create.recipe.blockzapper_upgrade": "Портативный размещатель блоков",
"create.recipe.sandpaper_polishing": "UNLOCALIZED: Sandpaper Polishing",
"create.recipe.mystery_conversion": "UNLOCALIZED: Chromatic Metamorphosis",
"create.recipe.processing.catalyst": "UNLOCALIZED: Catalyst",
"create.recipe.mystery_conversion": "UNLOCALIZED: Mysterious Conversion",
"create.recipe.processing.chance": "%1$s%% шанс выпадения",
"create.recipe.processing.chanceToReturn": "UNLOCALIZED: %1$s%% Chance to Return",
"create.recipe.heat_requirement.none": "UNLOCALIZED: No Heating Required",
"create.recipe.heat_requirement.heated": "UNLOCALIZED: Heated",
"create.recipe.heat_requirement.superheated": "UNLOCALIZED: Super-Heated",
@ -578,7 +580,6 @@
"create.generic.unit.rpm": "UNLOCALIZED: RPM",
"create.generic.unit.stress": "UNLOCALIZED: su",
"create.generic.unit.degrees": "UNLOCALIZED: °",
"create.generic.unit.bucket": "UNLOCALIZED: 1 Bucket",
"create.generic.unit.millibuckets": "UNLOCALIZED: %1$smB",
"create.action.scroll": "КолМыши",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 217",
"_": "Missing Localizations: 221",
"_": "->------------------------] Game Elements [------------------------<-",
@ -379,6 +379,8 @@
"entity.create.stationary_contraption": "固定结构",
"entity.create.super_glue": "强力胶",
"fluid.create.flowing_potion": "UNLOCALIZED: Potion",
"item.create.andesite_alloy": "安山合金",
"item.create.attribute_filter": "属性过滤器",
"item.create.belt_connector": "传送带",
@ -541,26 +543,26 @@
"create.recipe.crushing": "粉碎",
"create.recipe.milling": "研磨",
"create.recipe.splashing": "洗涤",
"create.recipe.splashing.fan": "在鼓风机前方倒水",
"create.recipe.smoking_via_fan": "UNLOCALIZED: Bulk Smoking",
"create.recipe.smoking_via_fan.fan": "UNLOCALIZED: Fan behind Fire",
"create.recipe.blasting_via_fan": "UNLOCALIZED: Bulk Smelting",
"create.recipe.blasting_via_fan.fan": "UNLOCALIZED: Fan behind Lava",
"create.recipe.fan_washing": "UNLOCALIZED: Bulk Washing",
"create.recipe.fan_washing.fan": "UNLOCALIZED: Fan behind Flowing Water",
"create.recipe.fan_smoking": "UNLOCALIZED: Bulk Smoking",
"create.recipe.fan_smoking.fan": "UNLOCALIZED: Fan behind Fire",
"create.recipe.fan_blasting": "UNLOCALIZED: Bulk Blasting",
"create.recipe.fan_blasting.fan": "UNLOCALIZED: Fan behind Lava",
"create.recipe.pressing": "金属压片",
"create.recipe.mixing": "混合搅拌",
"create.recipe.shapeless_mixing": "UNLOCALIZED: Shapeless Crafting",
"create.recipe.automatic_shapeless": "UNLOCALIZED: Automated Shapeless Crafting",
"create.recipe.automatic_brewing": "UNLOCALIZED: Automated Brewing",
"create.recipe.packing": "压块塑形",
"create.recipe.automatic_packing": "UNLOCALIZED: Automated Packing",
"create.recipe.sawing": "UNLOCALIZED: Sawing",
"create.recipe.mechanical_crafting": "自动合成",
"create.recipe.mechanical_crafting_exclusive": "UNLOCALIZED: Mechanical Crafting",
"create.recipe.automatic_shaped": "UNLOCALIZED: Automated Shaped Crafting",
"create.recipe.block_cutting": "方块切割",
"create.recipe.blockzapper_upgrade": "UNLOCALIZED: Handheld Blockzapper",
"create.recipe.sandpaper_polishing": "砂纸抛光",
"create.recipe.mystery_conversion": "化合物变异",
"create.recipe.processing.catalyst": "催化剂",
"create.recipe.processing.chance": "%1$s%% 概率",
"create.recipe.processing.chanceToReturn": "%1$s%% 概率返还",
"create.recipe.heat_requirement.none": "UNLOCALIZED: No Heating Required",
"create.recipe.heat_requirement.heated": "UNLOCALIZED: Heated",
"create.recipe.heat_requirement.superheated": "UNLOCALIZED: Super-Heated",
@ -578,7 +580,6 @@
"create.generic.unit.rpm": "RPM",
"create.generic.unit.stress": "su",
"create.generic.unit.degrees": "°",
"create.generic.unit.bucket": "UNLOCALIZED: 1 Bucket",
"create.generic.unit.millibuckets": "UNLOCALIZED: %1$smB",
"create.action.scroll": "滚轮",

View file

@ -1,18 +0,0 @@
{
"type": "create:emptying",
"ingredients": [
{
"item": "minecraft:potion"
}
],
"results": [
{
"item": "minecraft:glass_bottle",
"count": 1
},
{
"fluid": "minecraft:water",
"amount": 250
}
]
}

View file

@ -1,21 +0,0 @@
{
"type": "create:filling",
"ingredients": [
{
"item": "minecraft:glass_bottle"
},
{
"fluidTag": "minecraft:water",
"amount": 250
}
],
"results": [
{
"item": "minecraft:potion",
"count": 1,
"nbt": {
"Potion": "minecraft:water"
}
}
]
}

View file

@ -2,11 +2,13 @@
"type": "create:mixing",
"ingredients": [
{
"fluidTag": "minecraft:water",
"fluid": "minecraft:water",
"nbt": {},
"amount": 250
},
{
"fluidTag": "minecraft:lava",
"fluid": "minecraft:lava",
"nbt": {},
"amount": 25
}
],

View file

@ -0,0 +1,21 @@
package com.simibubi.create;
import com.simibubi.create.content.contraptions.fluids.potion.PotionFluid;
import com.simibubi.create.content.contraptions.fluids.potion.PotionFluid.PotionFluidAttributes;
import com.simibubi.create.foundation.data.CreateRegistrate;
import com.tterrag.registrate.util.entry.RegistryEntry;
public class AllFluids {
private static final CreateRegistrate REGISTRATE = Create.registrate();
public static RegistryEntry<PotionFluid> POTION =
REGISTRATE.virtualFluid("potion", PotionFluidAttributes::new, PotionFluid::new)
.lang(f -> "fluid.create.flowing_potion", "Potion")
.register();
// Load this class
public static void register() {}
}

View file

@ -75,6 +75,7 @@ public class Create {
AllBlocks.register();
AllItems.register();
AllFluids.register();
AllTags.register();
AllPaletteBlocks.register();
AllEntityTypes.register();

View file

@ -1,91 +1,178 @@
package com.simibubi.create.compat.jei;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import com.google.common.base.Predicates;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllItems;
import com.simibubi.create.AllRecipeTypes;
import com.simibubi.create.Create;
import com.simibubi.create.compat.jei.category.*;
import com.simibubi.create.compat.jei.category.BlockCuttingCategory;
import com.simibubi.create.compat.jei.category.BlockCuttingCategory.CondensedBlockCuttingRecipe;
import com.simibubi.create.compat.jei.category.BlockzapperUpgradeCategory;
import com.simibubi.create.compat.jei.category.CreateRecipeCategory;
import com.simibubi.create.compat.jei.category.CrushingCategory;
import com.simibubi.create.compat.jei.category.FanBlastingCategory;
import com.simibubi.create.compat.jei.category.FanSmokingCategory;
import com.simibubi.create.compat.jei.category.FanWashingCategory;
import com.simibubi.create.compat.jei.category.MechanicalCraftingCategory;
import com.simibubi.create.compat.jei.category.MillingCategory;
import com.simibubi.create.compat.jei.category.MixingCategory;
import com.simibubi.create.compat.jei.category.MysteriousItemConversionCategory;
import com.simibubi.create.compat.jei.category.PackingCategory;
import com.simibubi.create.compat.jei.category.PolishingCategory;
import com.simibubi.create.compat.jei.category.PressingCategory;
import com.simibubi.create.compat.jei.category.ProcessingViaFanCategory;
import com.simibubi.create.compat.jei.category.SawingCategory;
import com.simibubi.create.content.contraptions.components.press.MechanicalPressTileEntity;
import com.simibubi.create.content.contraptions.fluids.potion.PotionMixingRecipeManager;
import com.simibubi.create.content.contraptions.processing.BasinRecipe;
import com.simibubi.create.content.logistics.block.inventories.AdjustableCrateScreen;
import com.simibubi.create.content.logistics.item.filter.AbstractFilterScreen;
import com.simibubi.create.content.schematics.block.SchematicannonScreen;
import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.config.CRecipes;
import com.simibubi.create.foundation.fluid.FluidIngredient;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.config.ConfigBase.ConfigBool;
import mezz.jei.api.IModPlugin;
import mezz.jei.api.JeiPlugin;
import mezz.jei.api.ingredients.IIngredientType;
import mezz.jei.api.registration.*;
import net.minecraft.block.Blocks;
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.ISubtypeRegistration;
import net.minecraft.client.Minecraft;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.*;
import net.minecraft.item.crafting.ICraftingRecipe;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.item.crafting.IRecipeSerializer;
import net.minecraft.item.crafting.IRecipeType;
import net.minecraft.item.crafting.ShapedRecipe;
import net.minecraft.util.IItemProvider;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.util.text.TextFormatting;
import javax.annotation.Nonnull;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
@JeiPlugin
public class CreateJEI implements IModPlugin {
private static final ResourceLocation ID = new ResourceLocation(Create.ID, "jei_plugin");
public static final IIngredientType<FluidIngredient> FLUIDS = new IIngredientType<FluidIngredient>() {
@Override
@Nonnull
public Class<? extends FluidIngredient> getIngredientClass() {
return FluidIngredient.class;
}
};
private final MillingCategory millingCategory;
private final CrushingCategory crushingCategory;
private final SplashingCategory splashingCategory;
private final SmokingViaFanCategory smokingCategory;
private final PressingCategory pressingCategory;
private final BlastingViaFanCategory blastingCategory;
private final BlockzapperUpgradeCategory blockzapperCategory;
private final MixingCategory shapelessMixingCategory;
private final MixingCategory mixingCategory;
private final SawingCategory sawingCategory;
private final BlockCuttingCategory blockCuttingCategory;
private final PackingCategory packingCategory;
private final PolishingCategory polishingCategory;
private final MysteriousItemConversionCategory mysteryConversionCategory;
private final MechanicalCraftingCategory mechanicalCraftingCategory;
private final MechanicalCraftingCategory mechanicalCraftingExclusiveCategory;
@Override
@Nonnull
public ResourceLocation getPluginUid() {
return ID;
}
public CreateJEI() {
millingCategory = new MillingCategory();
crushingCategory = new CrushingCategory();
splashingCategory = new SplashingCategory();
pressingCategory = new PressingCategory();
smokingCategory = new SmokingViaFanCategory();
blastingCategory = new BlastingViaFanCategory();
blockzapperCategory = new BlockzapperUpgradeCategory();
shapelessMixingCategory = new MixingCategory(true);
mixingCategory = new MixingCategory(false);
sawingCategory = new SawingCategory();
blockCuttingCategory = new BlockCuttingCategory();
packingCategory = new PackingCategory();
polishingCategory = new PolishingCategory();
mysteryConversionCategory = new MysteriousItemConversionCategory();
mechanicalCraftingCategory = new MechanicalCraftingCategory(true);
mechanicalCraftingExclusiveCategory = new MechanicalCraftingCategory(false);
final List<CreateRecipeCategory<?>> ALL = new ArrayList<>();
final CreateRecipeCategory<?>
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)
.catalyst(AllBlocks.CRUSHING_WHEEL::get)
.build(),
pressing = register("pressing", PressingCategory::new).recipes(AllRecipeTypes.PRESSING)
.catalyst(AllBlocks.MECHANICAL_PRESS::get)
.build(),
washing = register("fan_washing", FanWashingCategory::new).recipes(AllRecipeTypes.SPLASHING)
.catalystStack(ProcessingViaFanCategory.getFan("fan_washing"))
.build(),
smoking = register("fan_smoking", FanSmokingCategory::new).recipes(() -> IRecipeType.SMOKING)
.catalystStack(ProcessingViaFanCategory.getFan("fan_smoking"))
.build(),
blasting = register("fan_blasting", FanBlastingCategory::new)
.recipesExcluding(() -> IRecipeType.SMELTING, () -> IRecipeType.SMOKING)
.catalystStack(ProcessingViaFanCategory.getFan("fan_blasting"))
.build(),
blockzapper = register("blockzapper_upgrade", BlockzapperUpgradeCategory::new)
.recipes(AllRecipeTypes.BLOCKZAPPER_UPGRADE.serializer.getRegistryName())
.catalyst(AllItems.BLOCKZAPPER::get)
.build(),
mixing = register("mixing", MixingCategory::standard).recipes(AllRecipeTypes.MIXING::getType)
.catalyst(AllBlocks.MECHANICAL_MIXER::get)
.catalyst(AllBlocks.BASIN::get)
.build(),
autoShapeless = register("automatic_shapeless", MixingCategory::autoShapeless)
.recipes(r -> r.getSerializer() == IRecipeSerializer.CRAFTING_SHAPELESS
&& !MechanicalPressTileEntity.canCompress(r.getIngredients()), BasinRecipe::convertShapeless)
.catalyst(AllBlocks.MECHANICAL_MIXER::get)
.catalyst(AllBlocks.BASIN::get)
.enableWhen(c -> c.allowShapelessInMixer)
.build(),
brewing = register("automatic_brewing", MixingCategory::autoBrewing)
.recipeList(PotionMixingRecipeManager::getAllBrewingRecipes)
.catalyst(AllBlocks.MECHANICAL_MIXER::get)
.catalyst(AllBlocks.BASIN::get)
.build(),
sawing = register("sawing", SawingCategory::new).recipes(AllRecipeTypes.CUTTING)
.catalyst(AllBlocks.MECHANICAL_SAW::get)
.build(),
blockCutting = register("block_cutting", BlockCuttingCategory::new)
.recipeList(() -> CondensedBlockCuttingRecipe.condenseRecipes(findRecipesByType(IRecipeType.STONECUTTING)))
.catalyst(AllBlocks.MECHANICAL_SAW::get)
.enableWhen(c -> c.allowStonecuttingOnSaw)
.build(),
packing = register("packing", PackingCategory::standard).recipes(AllRecipeTypes.COMPACTING)
.catalyst(AllBlocks.MECHANICAL_PRESS::get)
.catalyst(AllBlocks.BASIN::get)
.build(),
autoSquare = register("automatic_packing", PackingCategory::autoSquare)
.recipes(r -> (r instanceof ICraftingRecipe) && MechanicalPressTileEntity.canCompress(r.getIngredients()),
BasinRecipe::convertShapeless)
.catalyst(AllBlocks.MECHANICAL_PRESS::get)
.catalyst(AllBlocks.BASIN::get)
.enableWhen(c -> c.allowShapedSquareInPress)
.build(),
polishing = register("sandpaper_polishing", PolishingCategory::new).recipes(AllRecipeTypes.SANDPAPER_POLISHING)
.catalyst(AllItems.SAND_PAPER::get)
.catalyst(AllItems.RED_SAND_PAPER::get)
.build(),
mysteryConversion = register("mystery_conversion", MysteriousItemConversionCategory::new)
.recipeList(MysteriousItemConversionCategory::getRecipes)
.build(),
autoShaped = register("automatic_shaped", MechanicalCraftingCategory::new)
.recipes(
r -> (r.getType() == IRecipeType.CRAFTING && r.getType() != AllRecipeTypes.MECHANICAL_CRAFTING.type)
&& (r instanceof ShapedRecipe))
.catalyst(AllBlocks.MECHANICAL_CRAFTER::get)
.enableWhen(c -> c.allowRegularCraftingInCrafter)
.build(),
mechanicalCrafting =
register("mechanical_crafting", MechanicalCraftingCategory::new).recipes(AllRecipeTypes.MECHANICAL_CRAFTING)
.catalyst(AllBlocks.MECHANICAL_CRAFTER::get)
.build()
;
private <T extends IRecipe<?>> CategoryBuilder<T> register(String name,
Supplier<CreateRecipeCategory<T>> supplier) {
return new CategoryBuilder<T>(name, supplier);
}
@Override
@ -95,136 +182,135 @@ public class CreateJEI implements IModPlugin {
@Override
public void registerCategories(IRecipeCategoryRegistration registration) {
registration.addRecipeCategories(millingCategory, crushingCategory, splashingCategory, pressingCategory, smokingCategory, blastingCategory, blockzapperCategory, mixingCategory, shapelessMixingCategory, sawingCategory, blockCuttingCategory, packingCategory, polishingCategory, mysteryConversionCategory, mechanicalCraftingCategory, mechanicalCraftingExclusiveCategory);
ALL.forEach(registration::addRecipeCategories);
}
@Override
public void registerRecipes(IRecipeRegistration registration) {
CRecipes recipeConfig = AllConfigs.SERVER.recipes;
registration.addRecipes(findRecipes(AllRecipeTypes.MILLING), millingCategory.getUid());
registration.addRecipes(findRecipes(AllRecipeTypes.CRUSHING), crushingCategory.getUid());
registration.addRecipes(findRecipesByTypeExcluding(AllRecipeTypes.MILLING.getType(), AllRecipeTypes.CRUSHING.getType()), crushingCategory.getUid());
registration.addRecipes(findRecipes(AllRecipeTypes.SPLASHING), splashingCategory.getUid());
registration.addRecipes(findRecipes(AllRecipeTypes.PRESSING), pressingCategory.getUid());
registration.addRecipes(findRecipesById(AllRecipeTypes.BLOCKZAPPER_UPGRADE.serializer.getRegistryName()), blockzapperCategory.getUid());
registration.addRecipes(findRecipesByType(IRecipeType.SMOKING), smokingCategory.getUid());
registration.addRecipes(findRecipesByTypeExcluding(IRecipeType.SMELTING, IRecipeType.SMOKING), blastingCategory.getUid());
registration.addRecipes(findRecipes(AllRecipeTypes.MIXING), mixingCategory.getUid());
if (recipeConfig.allowShapelessInMixer.get())
registration.addRecipes(
findRecipes(r -> r.getSerializer() == IRecipeSerializer.CRAFTING_SHAPELESS && !MechanicalPressTileEntity.canCompress(r.getIngredients()))
.stream()
.map(BasinRecipe::convert)
.collect(Collectors.toList()),
shapelessMixingCategory.getUid());
registration.addRecipes(findRecipes(AllRecipeTypes.CUTTING), sawingCategory.getUid());
if (recipeConfig.allowStonecuttingOnSaw.get())
registration.addRecipes(CondensedBlockCuttingRecipe.condenseRecipes(findRecipesByType(IRecipeType.STONECUTTING)), blockCuttingCategory.getUid());
registration.addRecipes(findRecipes(AllRecipeTypes.COMPACTING), packingCategory.getUid());
if (recipeConfig.allowShapedSquareInPress.get())
registration.addRecipes(
findRecipes(r -> (r instanceof ICraftingRecipe) && MechanicalPressTileEntity.canCompress(r.getIngredients()))
.stream()
.map(BasinRecipe::convert)
.collect(Collectors.toList()),
packingCategory.getUid());
registration.addRecipes(findRecipes(AllRecipeTypes.SANDPAPER_POLISHING), polishingCategory.getUid());
registration.addRecipes(MysteriousItemConversionCategory.getRecipes(), mysteryConversionCategory.getUid());
registration.addRecipes(findRecipes(r -> (r.getType() == AllRecipeTypes.MECHANICAL_CRAFTING.type)), mechanicalCraftingExclusiveCategory.getUid());
if (recipeConfig.allowRegularCraftingInCrafter.get())
registration.addRecipes(
findRecipes(r -> (r.getType() == IRecipeType.CRAFTING && r.getType() != AllRecipeTypes.MECHANICAL_CRAFTING.type) && (r instanceof ShapedRecipe)),
mechanicalCraftingCategory.getUid());
ALL.forEach(c -> c.recipes.forEach(s -> registration.addRecipes(s.get(), c.getUid())));
}
@Override
public void registerRecipeCatalysts(IRecipeCatalystRegistration registration) {
ItemStack fan = new ItemStack(AllBlocks.ENCASED_FAN.get());
ItemStack splashingFan = fan.copy().setDisplayName(new StringTextComponent(TextFormatting.RESET + Lang.translate("recipe.splashing.fan")));
ItemStack smokingFan = fan.copy().setDisplayName(new StringTextComponent(TextFormatting.RESET + Lang.translate("recipe.smokingViaFan.fan")));
ItemStack blastingFan = fan.copy().setDisplayName(new StringTextComponent(TextFormatting.RESET + Lang.translate("recipe.blastingViaFan.fan")));
registration.addRecipeCatalyst(new ItemStack(AllBlocks.MILLSTONE.get()), millingCategory.getUid());
registration.addRecipeCatalyst(new ItemStack(AllBlocks.CRUSHING_WHEEL.get()), crushingCategory.getUid());
registration.addRecipeCatalyst(splashingFan, splashingCategory.getUid());
registration.addRecipeCatalyst(smokingFan, smokingCategory.getUid());
registration.addRecipeCatalyst(blastingFan, blastingCategory.getUid());
registration.addRecipeCatalyst(new ItemStack(AllBlocks.MECHANICAL_PRESS.get()), pressingCategory.getUid());
registration.addRecipeCatalyst(new ItemStack(AllItems.BLOCKZAPPER.get()), blockzapperCategory.getUid());
registration.addRecipeCatalyst(new ItemStack(AllBlocks.MECHANICAL_MIXER.get()), shapelessMixingCategory.getUid());
registration.addRecipeCatalyst(new ItemStack(AllBlocks.BASIN.get()), shapelessMixingCategory.getUid());
registration.addRecipeCatalyst(new ItemStack(AllBlocks.MECHANICAL_MIXER.get()), mixingCategory.getUid());
registration.addRecipeCatalyst(new ItemStack(AllBlocks.BASIN.get()), mixingCategory.getUid());
registration.addRecipeCatalyst(new ItemStack(AllBlocks.MECHANICAL_SAW.get()), sawingCategory.getUid());
registration.addRecipeCatalyst(new ItemStack(AllBlocks.MECHANICAL_SAW.get()), blockCuttingCategory.getUid());
registration.addRecipeCatalyst(new ItemStack(Blocks.STONECUTTER), blockCuttingCategory.getUid());
registration.addRecipeCatalyst(new ItemStack(AllBlocks.MECHANICAL_PRESS.get()), packingCategory.getUid());
registration.addRecipeCatalyst(new ItemStack(AllBlocks.BASIN.get()), packingCategory.getUid());
registration.addRecipeCatalyst(AllItems.SAND_PAPER.asStack(), polishingCategory.getUid());
registration.addRecipeCatalyst(AllItems.RED_SAND_PAPER.asStack(), polishingCategory.getUid());
registration.addRecipeCatalyst(new ItemStack(AllBlocks.MECHANICAL_CRAFTER.get()), mechanicalCraftingCategory.getUid());
registration.addRecipeCatalyst(new ItemStack(AllBlocks.MECHANICAL_CRAFTER.get()), mechanicalCraftingExclusiveCategory.getUid());
ALL.forEach(c -> c.recipeCatalysts.forEach(s -> registration.addRecipeCatalyst(s.get(), c.getUid())));
}
@Override
public void registerGuiHandlers(IGuiHandlerRegistration registration) {
registration.addGuiContainerHandler(AdjustableCrateScreen.class, new SlotMover<>());
registration.addGuiContainerHandler(SchematicannonScreen.class, new SlotMover<>());
registration.addGhostIngredientHandler(AbstractFilterScreen.class, new FilterGhostIngredientHandler());
}
private static List<IRecipe<?>> findRecipes(AllRecipeTypes recipe) {
return findRecipesByType(recipe.type);
private class CategoryBuilder<T extends IRecipe<?>> {
CreateRecipeCategory<T> category;
private Predicate<CRecipes> pred;
CategoryBuilder(String name, Supplier<CreateRecipeCategory<T>> category) {
this.category = category.get();
this.category.setCategoryId(name);
this.pred = Predicates.alwaysTrue();
}
CategoryBuilder<T> catalyst(Supplier<IItemProvider> supplier) {
return catalystStack(() -> new ItemStack(supplier.get().asItem()));
}
CategoryBuilder<T> catalystStack(Supplier<ItemStack> supplier) {
category.recipeCatalysts.add(supplier);
return this;
}
CategoryBuilder<T> recipes(AllRecipeTypes recipeTypeEntry) {
return recipes(recipeTypeEntry::getType);
}
CategoryBuilder<T> recipes(Supplier<IRecipeType<T>> recipeType) {
return recipes(r -> r.getType() == recipeType.get());
}
CategoryBuilder<T> recipes(ResourceLocation serializer) {
return recipes(r -> r.getSerializer()
.getRegistryName()
.equals(serializer));
}
CategoryBuilder<T> recipes(Predicate<IRecipe<?>> pred) {
return recipeList(() -> findRecipes(pred));
}
CategoryBuilder<T> recipes(Predicate<IRecipe<?>> pred, Function<IRecipe<?>, T> converter) {
return recipeList(() -> findRecipes(pred), converter);
}
CategoryBuilder<T> recipeList(Supplier<List<? extends IRecipe<?>>> list) {
return recipeList(list, null);
}
CategoryBuilder<T> recipeList(Supplier<List<? extends IRecipe<?>>> list, Function<IRecipe<?>, T> converter) {
category.recipes.add(() -> {
if (!this.pred.test(AllConfigs.SERVER.recipes))
return Collections.emptyList();
if (converter != null)
return list.get()
.stream()
.map(converter)
.collect(Collectors.toList());
return list.get();
});
return this;
}
CategoryBuilder<T> recipesExcluding(Supplier<IRecipeType<? extends T>> recipeType,
Supplier<IRecipeType<? extends T>> excluded) {
category.recipes.add(() -> {
if (!this.pred.test(AllConfigs.SERVER.recipes))
return Collections.emptyList();
return findRecipesByTypeExcluding(recipeType.get(), excluded.get());
});
return this;
}
CategoryBuilder<T> enableWhen(Function<CRecipes, ConfigBool> configValue) {
this.pred = c -> configValue.apply(c)
.get()
.booleanValue();
return this;
}
CreateRecipeCategory<T> build() {
ALL.add(category);
return category;
}
}
private static List<IRecipe<?>> findRecipes(Predicate<IRecipe<?>> predicate) {
return Minecraft.getInstance().world.getRecipeManager()
.getRecipes()
.stream()
.filter(predicate)
.collect(Collectors.toList());
}
private static List<IRecipe<?>> findRecipesByType(IRecipeType<?> type) {
static List<IRecipe<?>> findRecipesByType(IRecipeType<?> type) {
return findRecipes(r -> r.getType() == type);
}
private static List<IRecipe<?>> findRecipesById(ResourceLocation id) {
return findRecipes(r -> r.getSerializer().getRegistryName().equals(id));
static List<IRecipe<?>> findRecipes(Predicate<IRecipe<?>> predicate) {
return Minecraft.getInstance().world.getRecipeManager()
.getRecipes()
.stream()
.filter(predicate)
.collect(Collectors.toList());
}
private static List<IRecipe<?>> findRecipesByTypeExcluding(IRecipeType<?> type, IRecipeType<?> excludingType) {
List<IRecipe<?>> byType = findRecipesByType(type);
List<IRecipe<?>> byExcludingType = findRecipesByType(excludingType);
static List<IRecipe<?>> findRecipesByTypeExcluding(IRecipeType<?> type, IRecipeType<?> excludingType) {
List<IRecipe<?>> byType = findRecipes(r -> r.getType() == type);
List<IRecipe<?>> byExcludingType = findRecipes(r -> r.getType() == excludingType);
byType.removeIf(recipe -> {
for (IRecipe<?> r : byExcludingType) {
ItemStack[] matchingStacks = recipe.getIngredients().get(0).getMatchingStacks();
if (matchingStacks.length == 0) return true;
if (r.getIngredients().get(0).test(matchingStacks[0])) return true;
ItemStack[] matchingStacks = recipe.getIngredients()
.get(0)
.getMatchingStacks();
if (matchingStacks.length == 0)
return true;
if (r.getIngredients()
.get(0)
.test(matchingStacks[0]))
return true;
}
return false;
});

View file

@ -32,8 +32,11 @@ import net.minecraftforge.fluids.FluidStack;
public class BasinCategory extends CreateRecipeCategory<BasinRecipe> {
public BasinCategory(String id, IDrawable icon, IDrawable background) {
super(id, icon, background);
private boolean needsHeating;
public BasinCategory(boolean needsHeating, IDrawable icon, IDrawable background) {
super(icon, background);
this.needsHeating = needsHeating;
}
@Override
@ -44,13 +47,13 @@ public class BasinCategory extends CreateRecipeCategory<BasinRecipe> {
@Override
public void setIngredients(BasinRecipe recipe, IIngredients ingredients) {
List<Ingredient> itemIngredients = new ArrayList<>(recipe.getIngredients());
HeatCondition requiredHeat = recipe.getRequiredHeat();
if (!requiredHeat.testBlazeBurner(HeatLevel.NONE))
itemIngredients.add(Ingredient.fromItems(AllBlocks.BLAZE_BURNER.get()));
if (!requiredHeat.testBlazeBurner(HeatLevel.KINDLED))
itemIngredients.add(Ingredient.fromItems(AllItems.BLAZE_CAKE.get()));
ingredients.setInputIngredients(itemIngredients);
ingredients.setInputLists(VanillaTypes.FLUID, recipe.getFluidIngredients()
.stream()
@ -108,7 +111,7 @@ public class BasinCategory extends CreateRecipeCategory<BasinRecipe> {
fluidStacks.init(j, true, 17 + xOffset + (i2 % 3) * 19, 51 - (i2 / 3) * 19 + yOffset);
List<FluidStack> stacks = fluidIngredients.get(j)
.getMatchingFluidStacks();
fluidStacks.set(j, stacks);
fluidStacks.set(j, withImprovedVisibility(stacks));
}
if (!itemOutput.isEmpty()) {
@ -120,11 +123,11 @@ public class BasinCategory extends CreateRecipeCategory<BasinRecipe> {
if (!fluidOutput.isEmpty()) {
fluidStacks.init(j, false, 142, 51 + yOffset);
fluidStacks.set(j, fluidOutput);
fluidStacks.set(j, withImprovedVisibility(fluidOutput));
}
addFluidTooltip(fluidStacks, fluidIngredients, ImmutableList.of(fluidOutput));
HeatCondition requiredHeat = recipe.getRequiredHeat();
if (!requiredHeat.testBlazeBurner(HeatLevel.NONE)) {
itemStacks.init(++i, true, 133, 80);
@ -136,6 +139,19 @@ public class BasinCategory extends CreateRecipeCategory<BasinRecipe> {
}
}
public List<FluidStack> withImprovedVisibility(List<FluidStack> stacks) {
return stacks.stream()
.map(this::withImprovedVisibility)
.collect(Collectors.toList());
}
public FluidStack withImprovedVisibility(FluidStack stack) {
FluidStack display = stack.copy();
int displayedAmount = (int) (stack.getAmount() * .75f) + 250;
display.setAmount(displayedAmount);
return display;
}
@Override
public void draw(BasinRecipe recipe, double mouseX, double mouseY) {
List<Pair<Ingredient, MutableInt>> actualIngredients = ItemHelper.condenseIngredients(recipe.getIngredients());
@ -156,9 +172,11 @@ public class BasinCategory extends CreateRecipeCategory<BasinRecipe> {
AllGuiTextures shadow = noHeat ? AllGuiTextures.JEI_SHADOW : AllGuiTextures.JEI_LIGHT;
shadow.draw(81, 58 + (noHeat ? 10 : 30));
if (!needsHeating)
return;
AllGuiTextures heatBar = noHeat ? AllGuiTextures.JEI_NO_HEAT_BAR : AllGuiTextures.JEI_HEAT_BAR;
heatBar.draw(4, 80);
Minecraft.getInstance().fontRenderer.drawStringWithShadow(Lang.translate(requiredHeat.getTranslationKey()), 9,
85, requiredHeat.getColor());
}

View file

@ -26,7 +26,7 @@ public class BlockCuttingCategory extends CreateRecipeCategory<CondensedBlockCut
private AnimatedSaw saw = new AnimatedSaw();
public BlockCuttingCategory() {
super("block_cutting", doubleItemIcon(AllBlocks.MECHANICAL_SAW.get(), Items.STONE_BRICK_STAIRS), emptyBackground(177, 70));
super(doubleItemIcon(AllBlocks.MECHANICAL_SAW.get(), Items.STONE_BRICK_STAIRS), emptyBackground(177, 70));
}
@Override

View file

@ -29,8 +29,7 @@ import net.minecraft.util.text.ITextComponent;
public class BlockzapperUpgradeCategory extends CreateRecipeCategory<BlockzapperUpgradeRecipe> {
public BlockzapperUpgradeCategory() {
super("blockzapper_upgrade", itemIcon(AllItems.BLOCKZAPPER.get()),
new ScreenResourceWrapper(BLOCKZAPPER_UPGRADE_RECIPE));
super(itemIcon(AllItems.BLOCKZAPPER.get()), new ScreenResourceWrapper(BLOCKZAPPER_UPGRADE_RECIPE));
}
@Override
@ -57,7 +56,8 @@ public class BlockzapperUpgradeCategory extends CreateRecipeCategory<Blockzapper
for (int y = 0; y < shape.getRecipeHeight(); y++) {
for (int x = 0; x < shape.getRecipeWidth(); x++) {
itemStacks.init(i, true, left + x * 18, top + y * 18);
itemStacks.set(i, Arrays.asList(shapedIngredients.get(i).getMatchingStacks()));
itemStacks.set(i, Arrays.asList(shapedIngredients.get(i)
.getMatchingStacks()));
i++;
}
}
@ -69,28 +69,31 @@ public class BlockzapperUpgradeCategory extends CreateRecipeCategory<Blockzapper
if (mouseX < 91 || mouseX > 91 + 52 || mouseY < 1 || mouseY > 53)
return list;
list.addAll(recipe.getRecipeOutput()
.getTooltip(Minecraft.getInstance().player,
Minecraft.getInstance().gameSettings.advancedItemTooltips ? ITooltipFlag.TooltipFlags.ADVANCED
: ITooltipFlag.TooltipFlags.NORMAL)
.stream().map(ITextComponent::getFormattedText).collect(Collectors.toList()));
.getTooltip(Minecraft.getInstance().player,
Minecraft.getInstance().gameSettings.advancedItemTooltips ? ITooltipFlag.TooltipFlags.ADVANCED
: ITooltipFlag.TooltipFlags.NORMAL)
.stream()
.map(ITextComponent::getFormattedText)
.collect(Collectors.toList()));
return list;
}
@Override
public void draw(BlockzapperUpgradeRecipe recipe, double mouseX, double mouseY) {
FontRenderer font = Minecraft.getInstance().fontRenderer;
String componentName =
Lang.translate("blockzapper.component." + Lang.asId(recipe.getUpgradedComponent().name()));
String componentName = Lang.translate("blockzapper.component." + Lang.asId(recipe.getUpgradedComponent()
.name()));
String text = "+ " + recipe.getTier().color + componentName;
font.drawStringWithShadow(text, (BLOCKZAPPER_UPGRADE_RECIPE.width - font.getStringWidth(text)) / 2, 57,
0x8B8B8B);
0x8B8B8B);
RenderSystem.pushMatrix();
RenderSystem.translated(126, 0, 0);
RenderSystem.scaled(3.5, 3.5, 3.5);
RenderSystem.translated(-10, 0, 0);
RenderSystem.color3f(1, 1, 1);
GuiGameElement.of(recipe.getRecipeOutput()).render();
GuiGameElement.of(recipe.getRecipeOutput())
.render();
RenderSystem.popMatrix();
}
}

View file

@ -3,10 +3,14 @@ package com.simibubi.create.compat.jei.category;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import com.simibubi.create.AllFluids;
import com.simibubi.create.Create;
import com.simibubi.create.compat.jei.DoubleItemIcon;
import com.simibubi.create.compat.jei.EmptyBackground;
import com.simibubi.create.content.contraptions.fluids.potion.PotionFluidHandler;
import com.simibubi.create.content.contraptions.processing.ProcessingOutput;
import com.simibubi.create.content.contraptions.processing.ProcessingRecipe;
import com.simibubi.create.foundation.fluid.FluidIngredient;
@ -21,23 +25,30 @@ import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.util.IItemProvider;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextFormatting;
import net.minecraftforge.fluids.FluidStack;
public abstract class CreateRecipeCategory<T extends IRecipe<?>> implements IRecipeCategory<T> {
private ResourceLocation uid;
private String name;
public List<Supplier<? extends Object>> recipeCatalysts = new ArrayList<>();
public List<Supplier<List<? extends IRecipe<?>>>> recipes = new ArrayList<>();
public ResourceLocation uid;
protected String name;
private IDrawable icon;
private IDrawable background;
public CreateRecipeCategory(String id, IDrawable icon, IDrawable background) {
uid = new ResourceLocation(Create.ID, id);
name = id;
public CreateRecipeCategory(IDrawable icon, IDrawable background) {
this.background = background;
this.icon = icon;
}
public void setCategoryId(String name) {
this.uid = new ResourceLocation(Create.ID, name);
this.name = name;
}
@Override
public IDrawable getIcon() {
return icon;
@ -102,10 +113,25 @@ public abstract class CreateRecipeCategory<T extends IRecipe<?>> implements IRec
inputs.forEach(f -> amounts.add(f.getRequiredAmount()));
outputs.forEach(f -> amounts.add(f.getAmount()));
fluidStacks.addTooltipCallback((slotIndex, input, ingredient, tooltip) -> {
fluidStacks.addTooltipCallback((slotIndex, input, fluid, tooltip) -> {
if (fluid.getFluid()
.isEquivalentTo(AllFluids.POTION.get())) {
String name = PotionFluidHandler.getPotionName(fluid)
.getFormattedText();
if (tooltip.isEmpty())
tooltip.add(0, name);
else
tooltip.set(0, name);
ArrayList<ITextComponent> potionTooltip = new ArrayList<>();
PotionFluidHandler.addPotionTooltip(fluid, potionTooltip, 1);
tooltip.addAll(1, potionTooltip.stream()
.map(ITextComponent::getFormattedText)
.collect(Collectors.toList()));
}
int amount = amounts.get(slotIndex);
String text = TextFormatting.GOLD + (amount == 1000 ? Lang.translate("generic.unit.bucket")
: Lang.translate("generic.unit.millibuckets", amount));
String text = TextFormatting.GOLD + Lang.translate("generic.unit.millibuckets", amount);
if (tooltip.isEmpty())
tooltip.add(0, text);
else

View file

@ -20,8 +20,7 @@ public class CrushingCategory extends CreateRecipeCategory<AbstractCrushingRecip
private AnimatedCrushingWheels crushingWheels = new AnimatedCrushingWheels();
public CrushingCategory() {
super("crushing", doubleItemIcon(AllBlocks.CRUSHING_WHEEL.get(), AllItems.CRUSHED_GOLD.get()),
emptyBackground(177, 100));
super(doubleItemIcon(AllBlocks.CRUSHING_WHEEL.get(), AllItems.CRUSHED_GOLD.get()), emptyBackground(177, 100));
}
@Override
@ -39,14 +38,17 @@ public class CrushingCategory extends CreateRecipeCategory<AbstractCrushingRecip
public void setRecipe(IRecipeLayout recipeLayout, AbstractCrushingRecipe recipe, IIngredients ingredients) {
IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks();
itemStacks.init(0, true, 50, 2);
itemStacks.set(0, Arrays.asList(recipe.getIngredients().get(0).getMatchingStacks()));
itemStacks.set(0, Arrays.asList(recipe.getIngredients()
.get(0)
.getMatchingStacks()));
List<ProcessingOutput> results = recipe.getRollableResults();
int size = results.size();
int offset = -size * 19 / 2;
for (int outputIndex = 0; outputIndex < size; outputIndex++) {
itemStacks.init(outputIndex + 1, false, getBackground().getWidth() / 2 + offset + 19 * outputIndex, 78);
itemStacks.set(outputIndex + 1, results.get(outputIndex).getStack());
itemStacks.set(outputIndex + 1, results.get(outputIndex)
.getStack());
}
addStochasticTooltip(itemStacks, results);

View file

@ -8,10 +8,10 @@ import net.minecraft.fluid.Fluids;
import net.minecraft.item.Items;
import net.minecraft.item.crafting.AbstractCookingRecipe;
public class BlastingViaFanCategory extends ProcessingViaFanCategory<AbstractCookingRecipe> {
public class FanBlastingCategory extends ProcessingViaFanCategory<AbstractCookingRecipe> {
public BlastingViaFanCategory() {
super("blasting_via_fan", doubleItemIcon(AllItems.PROPELLER.get(), Items.LAVA_BUCKET));
public FanBlastingCategory() {
super(doubleItemIcon(AllItems.PROPELLER.get(), Items.LAVA_BUCKET));
}
@Override
@ -24,9 +24,9 @@ public class BlastingViaFanCategory extends ProcessingViaFanCategory<AbstractCoo
RenderSystem.pushMatrix();
GuiGameElement.of(Fluids.LAVA)
.scale(24)
.atLocal(0, 0, 2)
.render();
.scale(24)
.atLocal(0, 0, 2)
.render();
RenderSystem.popMatrix();
}

View file

@ -7,10 +7,10 @@ import net.minecraft.block.Blocks;
import net.minecraft.item.Items;
import net.minecraft.item.crafting.SmokingRecipe;
public class SmokingViaFanCategory extends ProcessingViaFanCategory<SmokingRecipe> {
public class FanSmokingCategory extends ProcessingViaFanCategory<SmokingRecipe> {
public SmokingViaFanCategory() {
super("smoking_via_fan", doubleItemIcon(AllItems.PROPELLER.get(), Items.BLAZE_POWDER));
public FanSmokingCategory() {
super(doubleItemIcon(AllItems.PROPELLER.get(), Items.BLAZE_POWDER));
}
@Override

View file

@ -17,10 +17,10 @@ import mezz.jei.api.ingredients.IIngredients;
import net.minecraft.fluid.Fluids;
import net.minecraft.item.Items;
public class SplashingCategory extends ProcessingViaFanCategory<SplashingRecipe> {
public class FanWashingCategory extends ProcessingViaFanCategory<SplashingRecipe> {
public SplashingCategory() {
super("splashing", doubleItemIcon(AllItems.PROPELLER.get(), Items.WATER_BUCKET));
public FanWashingCategory() {
super(doubleItemIcon(AllItems.PROPELLER.get(), Items.WATER_BUCKET));
}
@Override

View file

@ -1,9 +1,15 @@
package com.simibubi.create.compat.jei.category;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.compat.jei.category.animations.AnimatedCrafter;
import com.simibubi.create.foundation.gui.AllGuiTextures;
import mezz.jei.api.constants.VanillaTypes;
import mezz.jei.api.gui.IRecipeLayout;
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup;
@ -23,13 +29,107 @@ import net.minecraft.util.NonNullList;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextFormatting;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class MechanicalCraftingCategory extends CreateRecipeCategory<ShapedRecipe> {
private final AnimatedCrafter crafter = new AnimatedCrafter();
public MechanicalCraftingCategory() {
super(itemIcon(AllBlocks.MECHANICAL_CRAFTER.get()), emptyBackground(177, 107));
}
@Override
public void setIngredients(ShapedRecipe recipe, IIngredients ingredients) {
ingredients.setInputIngredients(recipe.getIngredients());
ingredients.setOutput(VanillaTypes.ITEM, recipe.getRecipeOutput());
}
@Override
public void setRecipe(IRecipeLayout recipeLayout, ShapedRecipe recipe, IIngredients ingredients) {
IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks();
NonNullList<Ingredient> recipeIngredients = recipe.getIngredients();
itemStacks.init(0, false, 133, 80);
itemStacks.set(0, recipe.getRecipeOutput()
.getStack());
int x = getXPadding(recipe);
int y = getYPadding(recipe);
float scale = getScale(recipe);
int size = recipeIngredients.size();
IIngredientRenderer<ItemStack> renderer = new CrafterIngredientRenderer(recipe);
for (int i = 0; i < size; i++) {
float f = 19 * scale;
int slotSize = (int) (16 * scale);
int xPosition = (int) (x + 1 + (i % recipe.getWidth()) * f);
int yPosition = (int) (y + 1 + (i / recipe.getWidth()) * f);
itemStacks.init(i + 1, true, renderer, xPosition, yPosition, slotSize, slotSize, 0, 0);
itemStacks.set(i + 1, Arrays.asList(recipeIngredients.get(i)
.getMatchingStacks()));
}
}
static int maxSize = 100;
public static float getScale(ShapedRecipe recipe) {
int w = recipe.getWidth();
int h = recipe.getHeight();
return Math.min(1, maxSize / (19f * Math.max(w, h)));
}
public static int getYPadding(ShapedRecipe recipe) {
return 3 + 50 - (int) (getScale(recipe) * recipe.getHeight() * 19 * .5);
}
public static int getXPadding(ShapedRecipe recipe) {
return 3 + 50 - (int) (getScale(recipe) * recipe.getWidth() * 19 * .5);
}
@Override
public void draw(ShapedRecipe recipe, double mouseX, double mouseY) {
RenderSystem.pushMatrix();
float scale = getScale(recipe);
RenderSystem.translated(getXPadding(recipe), getYPadding(recipe), 0);
for (int row = 0; row < recipe.getHeight(); row++)
for (int col = 0; col < recipe.getWidth(); col++)
if (!recipe.getIngredients()
.get(row * recipe.getWidth() + col)
.hasNoMatchingItems()) {
RenderSystem.pushMatrix();
RenderSystem.translated(col * 19 * scale, row * 19 * scale, 0);
RenderSystem.scaled(scale, scale, scale);
AllGuiTextures.JEI_SLOT.draw(0, 0);
RenderSystem.popMatrix();
}
RenderSystem.popMatrix();
AllGuiTextures.JEI_SLOT.draw(133, 80);
AllGuiTextures.JEI_DOWN_ARROW.draw(128, 59);
crafter.draw(129, 25);
RenderSystem.pushMatrix();
RenderSystem.translated(0, 0, 300);
RenderHelper.disableStandardItemLighting();
int amount = 0;
for (Ingredient ingredient : recipe.getIngredients()) {
if (Ingredient.EMPTY == ingredient)
continue;
amount++;
}
Minecraft.getInstance().fontRenderer.drawStringWithShadow(amount + "", 142, 39, 0xFFFFFF);
RenderSystem.popMatrix();
}
@Override
public Class<? extends ShapedRecipe> getRecipeClass() {
return ShapedRecipe.class;
}
private static final class CrafterIngredientRenderer implements IIngredientRenderer<ItemStack> {
private final ShapedRecipe recipe;
@ -66,11 +166,10 @@ public class MechanicalCraftingCategory extends CreateRecipeCategory<ShapedRecip
PlayerEntity player = minecraft.player;
List<String> list;
try {
list = ingredient
.getTooltip(player, tooltipFlag)
.stream()
.map(ITextComponent::getFormattedText)
.collect(Collectors.toList());
list = ingredient.getTooltip(player, tooltipFlag)
.stream()
.map(ITextComponent::getFormattedText)
.collect(Collectors.toList());
} catch (RuntimeException | LinkageError e) {
return new ArrayList<>();
}
@ -94,103 +193,4 @@ public class MechanicalCraftingCategory extends CreateRecipeCategory<ShapedRecip
}
}
private final AnimatedCrafter crafter = new AnimatedCrafter();
public MechanicalCraftingCategory(boolean isForNormalCraftingOnly) {
super(
isForNormalCraftingOnly ? "mechanical_crafting" : "mechanical_crafting_exclusive",
itemIcon(AllBlocks.MECHANICAL_CRAFTER.get()),
emptyBackground(177, 107));
}
@Override
public void setIngredients(ShapedRecipe recipe, IIngredients ingredients) {
ingredients.setInputIngredients(recipe.getIngredients());
ingredients.setOutput(VanillaTypes.ITEM, recipe.getRecipeOutput());
}
@Override
public void setRecipe(IRecipeLayout recipeLayout, ShapedRecipe recipe, IIngredients ingredients) {
IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks();
NonNullList<Ingredient> recipeIngredients = recipe.getIngredients();
itemStacks.init(0, false, 133, 80);
itemStacks.set(0, recipe.getRecipeOutput().getStack());
int x = getXPadding(recipe);
int y = getYPadding(recipe);
float scale = getScale(recipe);
int size = recipeIngredients.size();
IIngredientRenderer<ItemStack> renderer = new CrafterIngredientRenderer(recipe);
for (int i = 0; i < size; i++) {
float f = 19 * scale;
int slotSize = (int) (16 * scale);
int xPosition = (int) (x + 1 + (i % recipe.getWidth()) * f);
int yPosition = (int) (y + 1 + (i / recipe.getWidth()) * f);
itemStacks.init(i + 1, true, renderer, xPosition, yPosition, slotSize, slotSize, 0, 0);
itemStacks.set(i + 1, Arrays.asList(recipeIngredients.get(i).getMatchingStacks()));
}
}
static int maxSize = 100;
public static float getScale(ShapedRecipe recipe) {
int w = recipe.getWidth();
int h = recipe.getHeight();
return Math.min(1, maxSize / (19f * Math.max(w, h)));
}
public static int getYPadding(ShapedRecipe recipe) {
return 3 + 50 - (int) (getScale(recipe) * recipe.getHeight() * 19 * .5);
}
public static int getXPadding(ShapedRecipe recipe) {
return 3 + 50 - (int) (getScale(recipe) * recipe.getWidth() * 19 * .5);
}
@Override
public void draw(ShapedRecipe recipe, double mouseX, double mouseY) {
RenderSystem.pushMatrix();
float scale = getScale(recipe);
RenderSystem.translated(getXPadding(recipe), getYPadding(recipe), 0);
for (int row = 0; row < recipe.getHeight(); row++)
for (int col = 0; col < recipe.getWidth(); col++)
if (!recipe.getIngredients().get(row * recipe.getWidth() + col).hasNoMatchingItems()) {
RenderSystem.pushMatrix();
RenderSystem.translated(col * 19 * scale, row * 19 * scale, 0);
RenderSystem.scaled(scale, scale, scale);
AllGuiTextures.JEI_SLOT.draw(0, 0);
RenderSystem.popMatrix();
}
RenderSystem.popMatrix();
AllGuiTextures.JEI_SLOT.draw(133, 80);
AllGuiTextures.JEI_DOWN_ARROW.draw(128, 59);
crafter.draw(129, 25);
RenderSystem.pushMatrix();
RenderSystem.translated(0, 0, 300);
RenderHelper.disableStandardItemLighting();
int amount = 0;
for (Ingredient ingredient : recipe.getIngredients()) {
if (Ingredient.EMPTY == ingredient)
continue;
amount++;
}
Minecraft.getInstance().fontRenderer
.drawStringWithShadow(amount + "", 142, 39, 0xFFFFFF);
RenderSystem.popMatrix();
}
@Override
public Class<? extends ShapedRecipe> getRecipeClass() {
return ShapedRecipe.class;
}
}

View file

@ -20,8 +20,7 @@ public class MillingCategory extends CreateRecipeCategory<AbstractCrushingRecipe
private AnimatedMillstone millstone = new AnimatedMillstone();
public MillingCategory() {
super("milling", doubleItemIcon(AllBlocks.MILLSTONE.get(), AllItems.WHEAT_FLOUR.get()),
emptyBackground(177, 53));
super(doubleItemIcon(AllBlocks.MILLSTONE.get(), AllItems.WHEAT_FLOUR.get()), emptyBackground(177, 53));
}
@Override

View file

@ -6,16 +6,36 @@ import com.simibubi.create.compat.jei.category.animations.AnimatedMixer;
import com.simibubi.create.content.contraptions.processing.BasinRecipe;
import com.simibubi.create.content.contraptions.processing.HeatCondition;
import net.minecraft.block.Blocks;
import net.minecraft.item.Items;
import net.minecraft.util.IItemProvider;
public class MixingCategory extends BasinCategory {
private final AnimatedMixer mixer = new AnimatedMixer();
private final AnimatedBlazeBurner heater = new AnimatedBlazeBurner();
private MixingType type;
public MixingCategory(boolean isForShapelessCraftingOnly) {
super(
isForShapelessCraftingOnly ? "shapeless_mixing" : "mixing",
doubleItemIcon(AllBlocks.MECHANICAL_MIXER.get(), AllBlocks.BASIN.get()),
emptyBackground(177, 103));
enum MixingType {
AUTO_SHAPELESS, MIXING, AUTO_BREWING;
}
public static MixingCategory autoShapeless() {
return new MixingCategory(MixingType.AUTO_SHAPELESS, Items.CRAFTING_TABLE, 85);
}
public static MixingCategory standard() {
return new MixingCategory(MixingType.MIXING, AllBlocks.BASIN.get(), 103);
}
public static MixingCategory autoBrewing() {
return new MixingCategory(MixingType.AUTO_BREWING, Blocks.BREWING_STAND, 103);
}
protected MixingCategory(MixingType type, IItemProvider secondaryItem, int height) {
super(type != MixingType.AUTO_SHAPELESS, doubleItemIcon(AllBlocks.MECHANICAL_MIXER.get(), secondaryItem),
emptyBackground(177, height));
this.type = type;
}
@Override
@ -24,7 +44,7 @@ public class MixingCategory extends BasinCategory {
HeatCondition requiredHeat = recipe.getRequiredHeat();
if (requiredHeat != HeatCondition.NONE)
heater.withHeat(requiredHeat.visualizeAsBlazeBurner())
.draw(getBackground().getWidth() / 2 + 3, 55);
.draw(getBackground().getWidth() / 2 + 3, 55);
mixer.draw(getBackground().getWidth() / 2 + 3, 34);
}

View file

@ -4,6 +4,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllItems;
import com.simibubi.create.compat.jei.ConversionRecipe;
import com.simibubi.create.content.contraptions.processing.ProcessingOutput;
@ -18,13 +19,14 @@ public class MysteriousItemConversionCategory extends CreateRecipeCategory<Conve
public static List<ConversionRecipe> getRecipes() {
List<ConversionRecipe> recipes = new ArrayList<>();
recipes.add(ConversionRecipe.create(AllItems.EMPTY_BLAZE_BURNER.asStack(), AllBlocks.BLAZE_BURNER.asStack()));
recipes.add(ConversionRecipe.create(AllItems.CHROMATIC_COMPOUND.asStack(), AllItems.SHADOW_STEEL.asStack()));
recipes.add(ConversionRecipe.create(AllItems.CHROMATIC_COMPOUND.asStack(), AllItems.REFINED_RADIANCE.asStack()));
return recipes;
}
public MysteriousItemConversionCategory() {
super("mystery_conversion", itemIcon(AllItems.CHROMATIC_COMPOUND.get()), emptyBackground(177, 50));
super(itemIcon(AllItems.CHROMATIC_COMPOUND.get()), emptyBackground(177, 50));
}
@Override

View file

@ -10,25 +10,41 @@ import com.simibubi.create.foundation.gui.AllGuiTextures;
import mezz.jei.api.gui.IRecipeLayout;
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup;
import mezz.jei.api.ingredients.IIngredients;
import net.minecraft.block.Blocks;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.util.IItemProvider;
import net.minecraft.util.NonNullList;
public class PackingCategory extends BasinCategory {
private AnimatedPress press = new AnimatedPress(true);
private PackingType type;
public PackingCategory() {
super("packing", doubleItemIcon(AllBlocks.MECHANICAL_PRESS.get(), AllBlocks.BASIN.get()),
emptyBackground(177, 103));
enum PackingType {
AUTO_SQUARE, COMPACTING;
}
public static PackingCategory standard() {
return new PackingCategory(PackingType.COMPACTING, AllBlocks.BASIN.get(), 103);
}
public static PackingCategory autoSquare() {
return new PackingCategory(PackingType.AUTO_SQUARE, Blocks.CRAFTING_TABLE, 85);
}
protected PackingCategory(PackingType type, IItemProvider icon, int height) {
super(type != PackingType.AUTO_SQUARE, doubleItemIcon(AllBlocks.MECHANICAL_PRESS.get(), icon),
emptyBackground(177, height));
this.type = type;
}
@Override
public void setRecipe(IRecipeLayout recipeLayout, BasinRecipe recipe, IIngredients ingredients) {
if (!recipe.convertedRecipe) {
if (type == PackingType.COMPACTING) {
super.setRecipe(recipeLayout, recipe, ingredients);
return;
}
IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks();
int i = 0;
@ -48,21 +64,20 @@ public class PackingCategory extends BasinCategory {
@Override
public void draw(BasinRecipe recipe, double mouseX, double mouseY) {
if (!recipe.convertedRecipe) {
if (type == PackingType.COMPACTING) {
super.draw(recipe, mouseX, mouseY);
} else {
NonNullList<Ingredient> ingredients2 = recipe.getIngredients();
int size = ingredients2.size();
int rows = size == 4 ? 2 : 3;
for (int i = 0; i < size; i++)
for (int i = 0; i < size; i++)
AllGuiTextures.JEI_SLOT.draw((rows == 2 ? 26 : 17) + (i % rows) * 19, 50 - (i / rows) * 19);
AllGuiTextures.JEI_SLOT.draw(141, 50);
AllGuiTextures.JEI_DOWN_ARROW.draw(136, 32);
AllGuiTextures.JEI_SHADOW.draw(81, 68);
AllGuiTextures.JEI_NO_HEAT_BAR.draw(4, 80);
}
press.draw(getBackground().getWidth() / 2 + 6, 40);
}

View file

@ -25,7 +25,7 @@ public class PolishingCategory extends CreateRecipeCategory<SandPaperPolishingRe
private ItemStack renderedSandpaper;
public PolishingCategory() {
super("sandpaper_polishing", itemIcon(AllItems.SAND_PAPER.get()), emptyBackground(177, 55));
super(itemIcon(AllItems.SAND_PAPER.get()), emptyBackground(177, 55));
renderedSandpaper = AllItems.SAND_PAPER.asStack();
}
@ -46,9 +46,12 @@ public class PolishingCategory extends CreateRecipeCategory<SandPaperPolishingRe
List<ProcessingOutput> results = recipe.getRollableResults();
itemStacks.init(0, true, 26, 28);
itemStacks.set(0, Arrays.asList(recipe.getIngredients().get(0).getMatchingStacks()));
itemStacks.set(0, Arrays.asList(recipe.getIngredients()
.get(0)
.getMatchingStacks()));
itemStacks.init(1, false, 131, 28);
itemStacks.set(1, results.get(0).getStack());
itemStacks.set(1, results.get(0)
.getStack());
addStochasticTooltip(itemStacks, results);
}
@ -61,7 +64,8 @@ public class PolishingCategory extends CreateRecipeCategory<SandPaperPolishingRe
AllGuiTextures.JEI_LONG_ARROW.draw(52, 32);
NonNullList<Ingredient> ingredients = recipe.getIngredients();
ItemStack[] matchingStacks = ingredients.get(0).getMatchingStacks();
ItemStack[] matchingStacks = ingredients.get(0)
.getMatchingStacks();
if (matchingStacks.length == 0)
return;
@ -69,7 +73,8 @@ public class PolishingCategory extends CreateRecipeCategory<SandPaperPolishingRe
CompoundNBT tag = renderedSandpaper.getOrCreateTag();
tag.put("Polishing", matchingStacks[0].serializeNBT());
tag.putBoolean("JEI", true);
ItemRenderer itemRenderer = Minecraft.getInstance().getItemRenderer();
ItemRenderer itemRenderer = Minecraft.getInstance()
.getItemRenderer();
RenderSystem.scaled(2, 2, 2);
itemRenderer.renderItemIntoGUI(renderedSandpaper, getBackground().getWidth() / 4 - 8, 1);
RenderSystem.popMatrix();

View file

@ -20,8 +20,7 @@ public class PressingCategory extends CreateRecipeCategory<PressingRecipe> {
private AnimatedPress press = new AnimatedPress(false);
public PressingCategory() {
super("pressing", doubleItemIcon(AllBlocks.MECHANICAL_PRESS.get(), AllItems.IRON_SHEET.get()),
emptyBackground(177, 70));
super(doubleItemIcon(AllBlocks.MECHANICAL_PRESS.get(), AllItems.IRON_SHEET.get()), emptyBackground(177, 70));
}
@Override
@ -39,12 +38,15 @@ public class PressingCategory extends CreateRecipeCategory<PressingRecipe> {
public void setRecipe(IRecipeLayout recipeLayout, PressingRecipe recipe, IIngredients ingredients) {
IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks();
itemStacks.init(0, true, 26, 50);
itemStacks.set(0, Arrays.asList(recipe.getIngredients().get(0).getMatchingStacks()));
itemStacks.set(0, Arrays.asList(recipe.getIngredients()
.get(0)
.getMatchingStacks()));
List<ProcessingOutput> results = recipe.getRollableResults();
for (int outputIndex = 0; outputIndex < results.size(); outputIndex++) {
itemStacks.init(outputIndex + 1, false, 131 + 19 * outputIndex, 50);
itemStacks.set(outputIndex + 1, results.get(outputIndex).getStack());
itemStacks.set(outputIndex + 1, results.get(outputIndex)
.getStack());
}
addStochasticTooltip(itemStacks, results);
@ -54,7 +56,8 @@ public class PressingCategory extends CreateRecipeCategory<PressingRecipe> {
public void draw(PressingRecipe recipe, double mouseX, double mouseY) {
AllGuiTextures.JEI_SLOT.draw(26, 50);
getRenderedSlot(recipe, 0).draw(131, 50);
if (recipe.getRollableResults().size() > 1)
if (recipe.getRollableResults()
.size() > 1)
getRenderedSlot(recipe, 1).draw(131 + 19, 50);
AllGuiTextures.JEI_SHADOW.draw(61, 41);
AllGuiTextures.JEI_LONG_ARROW.draw(52, 54);

View file

@ -1,6 +1,7 @@
package com.simibubi.create.compat.jei.category;
import java.util.Arrays;
import java.util.function.Supplier;
import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.AllBlockPartials;
@ -8,18 +9,22 @@ import com.simibubi.create.AllBlocks;
import com.simibubi.create.compat.jei.category.animations.AnimatedKinetics;
import com.simibubi.create.foundation.gui.AllGuiTextures;
import com.simibubi.create.foundation.gui.GuiGameElement;
import com.simibubi.create.foundation.utility.Lang;
import mezz.jei.api.constants.VanillaTypes;
import mezz.jei.api.gui.IRecipeLayout;
import mezz.jei.api.gui.drawable.IDrawable;
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup;
import mezz.jei.api.ingredients.IIngredients;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.util.text.TextFormatting;
public abstract class ProcessingViaFanCategory<T extends IRecipe<?>> extends CreateRecipeCategory<T> {
public ProcessingViaFanCategory(String name, IDrawable icon) {
super(name, icon, emptyBackground(177, 70));
public ProcessingViaFanCategory(IDrawable icon) {
super(icon, emptyBackground(177, 70));
}
@Override
@ -28,6 +33,11 @@ public abstract class ProcessingViaFanCategory<T extends IRecipe<?>> extends Cre
ingredients.setOutput(VanillaTypes.ITEM, recipe.getRecipeOutput());
}
public static Supplier<ItemStack> getFan(String name) {
return () -> AllBlocks.ENCASED_FAN.asStack()
.setDisplayName(new StringTextComponent(TextFormatting.RESET + Lang.translate("recipe." + name + ".fan")));
}
@Override
public void setRecipe(IRecipeLayout recipeLayout, T recipe, IIngredients ingredients) {
IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks();

View file

@ -20,7 +20,7 @@ public class SawingCategory extends CreateRecipeCategory<CuttingRecipe> {
private AnimatedSaw saw = new AnimatedSaw();
public SawingCategory() {
super("sawing", doubleItemIcon(AllBlocks.MECHANICAL_SAW.get(), Items.OAK_LOG), emptyBackground(177, 70));
super(doubleItemIcon(AllBlocks.MECHANICAL_SAW.get(), Items.OAK_LOG), emptyBackground(177, 70));
}
@Override

View file

@ -1,9 +1,11 @@
package com.simibubi.create.content.contraptions.components.mixer;
import java.util.List;
import java.util.Optional;
import com.simibubi.create.AllRecipeTypes;
import com.simibubi.create.content.contraptions.components.press.MechanicalPressTileEntity;
import com.simibubi.create.content.contraptions.fluids.potion.PotionMixingRecipeManager;
import com.simibubi.create.content.contraptions.processing.BasinOperatingTileEntity;
import com.simibubi.create.content.contraptions.processing.BasinTileEntity;
import com.simibubi.create.foundation.advancement.AllTriggers;
@ -24,6 +26,8 @@ import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
public class MechanicalMixerTileEntity extends BasinOperatingTileEntity {
@ -151,6 +155,35 @@ public class MechanicalMixerTileEntity extends BasinOperatingTileEntity {
}
}
@Override
protected List<IRecipe<?>> getMatchingRecipes() {
List<IRecipe<?>> matchingRecipes = super.getMatchingRecipes();
Optional<BasinTileEntity> basin = getBasin();
if (!basin.isPresent())
return matchingRecipes;
IItemHandler availableItems = basin.get()
.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
.orElse(null);
if (availableItems == null)
return matchingRecipes;
for (int i = 0; i < availableItems.getSlots(); i++) {
ItemStack stack = availableItems.getStackInSlot(i);
if (stack.isEmpty())
continue;
List<MixingRecipe> list = PotionMixingRecipeManager.ALL.get(stack.getItem());
if (list == null)
continue;
for (MixingRecipe mixingRecipe : list)
if (matchBasinRecipe(mixingRecipe))
matchingRecipes.add(mixingRecipe);
}
return matchingRecipes;
}
@Override
protected <C extends IInventory> boolean matchStaticFilters(IRecipe<C> r) {
return ((r.getSerializer() == IRecipeSerializer.CRAFTING_SHAPELESS
@ -190,7 +223,7 @@ public class MechanicalMixerTileEntity extends BasinOperatingTileEntity {
protected boolean isRunning() {
return running;
}
@Override
protected Optional<ITriggerable> getProcessedRecipeTrigger() {
return Optional.of(AllTriggers.MIXER_MIX);

View file

@ -1,138 +0,0 @@
package com.simibubi.create.content.contraptions.fluids;
import java.util.Arrays;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import javax.annotation.Nonnull;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.ListNBT;
import net.minecraft.util.math.MathHelper;
import net.minecraftforge.common.util.NonNullConsumer;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.IFluidHandler;
public class CombinedFluidHandler implements IFluidHandler {
private final int capacity;
private final FluidStack[] tanks;
public CombinedFluidHandler(int tankNumber, int capacity) {
this.capacity = capacity;
this.tanks = new FluidStack[tankNumber];
Arrays.fill(tanks, FluidStack.EMPTY);
}
@Override
public int getTanks() {
return tanks.length;
}
@Nonnull
@Override
public FluidStack getFluidInTank(int tank) {
if (tank < 0 || tank >= tanks.length)
return FluidStack.EMPTY;
return tanks[tank];
}
@Override
public int getTankCapacity(int tank) {
return capacity;
}
@Override
public boolean isFluidValid(int tank, @Nonnull FluidStack stack) {
return (!stack.isEmpty()) && (tanks[tank].isEmpty() || tanks[tank].isFluidEqual(stack))
&& tanks[tank].getAmount() < capacity;
}
@Override
public int fill(FluidStack resource, FluidAction action) {
int tankIndex;
int amount = resource.getAmount();
while ((tankIndex = getFittingFluidSlot(resource)) != -1) {
int newAmount = MathHelper.clamp(amount - capacity - tanks[tankIndex].getAmount(), 0, Integer.MAX_VALUE);
if (action == FluidAction.EXECUTE)
if (tanks[tankIndex].isEmpty())
tanks[tankIndex] = new FluidStack(resource.getFluid(), amount - newAmount);
else
tanks[tankIndex].grow(amount - newAmount);
amount = newAmount;
if (amount == 0)
return 0;
}
return amount;
}
@Nonnull
@Override
public FluidStack drain(FluidStack resource, FluidAction action) {
if (resource.isEmpty())
return FluidStack.EMPTY;
FluidStack stack = new FluidStack(resource, 0);
for (int i = 0; i < tanks.length; i++) {
if (tanks[i].isFluidEqual(resource)) {
stack.grow(tanks[i].getAmount());
if (action == FluidAction.EXECUTE)
tanks[i] = FluidStack.EMPTY;
}
}
return stack.isEmpty() ? FluidStack.EMPTY : stack;
}
@Nonnull
@Override
public FluidStack drain(int maxDrain, FluidAction action) {
FluidStack stack = new FluidStack(tanks[0].getFluid(), 0);
for (int i = 0; i < tanks.length; i++) {
if (stack.isEmpty() || tanks[i].isFluidEqual(stack)) {
int newDrainAmount = MathHelper.clamp(stack.getAmount() + tanks[i].getAmount(), 0, maxDrain);
if (action == FluidAction.EXECUTE) {
tanks[i].shrink(newDrainAmount - stack.getAmount());
if (tanks[i].isEmpty())
tanks[i] = FluidStack.EMPTY;
}
if (stack.isEmpty())
stack = tanks[i].copy();
if (stack.isEmpty())
continue;
stack.setAmount(newDrainAmount);
}
}
return stack.isEmpty() ? FluidStack.EMPTY : stack;
}
private int getFittingFluidSlot(FluidStack fluidStack) {
return IntStream.range(0, tanks.length)
.filter(i -> isFluidValid(i, fluidStack))
.findFirst()
.orElse(-1);
}
private void setFluid(FluidStack fluid, int tank) {
tanks[tank] = fluid;
}
public CombinedFluidHandler readFromNBT(ListNBT fluidNBTs) {
for (int i = 0; i < Math.min(tanks.length, fluidNBTs.size()); i++)
setFluid(FluidStack.loadFluidStackFromNBT(fluidNBTs.getCompound(i)), i);
return this;
}
public ListNBT getListNBT() {
return Arrays.stream(tanks)
.map(fluid -> fluid.writeToNBT(new CompoundNBT()))
.collect(Collectors.toCollection(ListNBT::new));
}
public void forEachTank(NonNullConsumer<FluidStack> fluidStackConsumer) {
Arrays.stream(tanks)
.forEach(fluidStackConsumer::accept);
}
}

View file

@ -114,7 +114,7 @@ class FluidNetworkFlow {
return;
}
fluidStack = provideFluid;
fluidStack = provideFluid.copy();
// There is currently no unfinished flow being followed
if (flowPointers.isEmpty()) {

View file

@ -9,12 +9,7 @@ import com.simibubi.create.foundation.fluid.FluidIngredient;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.world.World;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction;
import net.minecraftforge.fluids.capability.IFluidHandlerItem;
import net.minecraftforge.fluids.capability.wrappers.FluidBucketWrapper;
import net.minecraftforge.items.ItemStackHandler;
import net.minecraftforge.items.wrapper.RecipeWrapper;
@ -27,18 +22,7 @@ public class FillingBySpout {
if (AllRecipeTypes.FILLING.find(wrapper, world)
.isPresent())
return true;
LazyOptional<IFluidHandlerItem> capability =
stack.getCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY);
IFluidHandlerItem tank = capability.orElse(null);
if (tank == null)
return false;
for (int i = 0; i < tank.getTanks(); i++) {
if (tank.getFluidInTank(i)
.getAmount() < tank.getTankCapacity(i))
return true;
}
return false;
return GenericItemFilling.canItemBeFilled(world, stack);
}
public static int getRequiredAmountForItem(World world, ItemStack stack, FluidStack availableFluid) {
@ -50,23 +34,12 @@ public class FillingBySpout {
if (requiredFluid.test(availableFluid))
return requiredFluid.getRequiredAmount();
}
LazyOptional<IFluidHandlerItem> capability =
stack.getCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY);
IFluidHandlerItem tank = capability.orElse(null);
if (tank == null)
return -1;
if (tank instanceof FluidBucketWrapper)
return 1000;
int filled = tank.fill(availableFluid, FluidAction.SIMULATE);
return filled == 0 ? -1 : filled;
return GenericItemFilling.getRequiredAmountForItem(world, stack, availableFluid);
}
public static ItemStack fillItem(World world, int requiredAmount, ItemStack stack, FluidStack availableFluid) {
FluidStack toFill = availableFluid.copy();
toFill.setAmount(requiredAmount);
availableFluid.shrink(requiredAmount);
wrapper.setInventorySlotContents(0, stack);
Optional<IRecipe<RecipeWrapper>> recipe = AllRecipeTypes.FILLING.find(wrapper, world);
@ -75,23 +48,12 @@ public class FillingBySpout {
FluidIngredient requiredFluid = fillingRecipe.getRequiredFluid();
if (requiredFluid.test(toFill)) {
List<ItemStack> results = fillingRecipe.rollResults();
availableFluid.shrink(requiredAmount);
stack.shrink(1);
return results.isEmpty() ? ItemStack.EMPTY : results.get(0);
}
}
ItemStack split = stack.copy();
split.setCount(1);
LazyOptional<IFluidHandlerItem> capability =
split.getCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY);
IFluidHandlerItem tank = capability.orElse(null);
if (tank == null)
return ItemStack.EMPTY;
tank.fill(toFill, FluidAction.EXECUTE);
ItemStack container = tank.getContainer()
.copy();
stack.shrink(1);
return container;
return GenericItemFilling.fillItem(world, requiredAmount, stack, availableFluid);
}
}

View file

@ -0,0 +1,82 @@
package com.simibubi.create.content.contraptions.fluids.actors;
import com.simibubi.create.content.contraptions.fluids.potion.PotionFluidHandler;
import com.simibubi.create.foundation.fluid.FluidHelper;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.potion.PotionUtils;
import net.minecraft.potion.Potions;
import net.minecraft.world.World;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction;
import net.minecraftforge.fluids.capability.IFluidHandlerItem;
import net.minecraftforge.fluids.capability.wrappers.FluidBucketWrapper;
public class GenericItemFilling {
public static boolean canItemBeFilled(World world, ItemStack stack) {
if (stack.getItem() == Items.GLASS_BOTTLE)
return true;
LazyOptional<IFluidHandlerItem> capability =
stack.getCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY);
IFluidHandlerItem tank = capability.orElse(null);
if (tank == null)
return false;
for (int i = 0; i < tank.getTanks(); i++) {
if (tank.getFluidInTank(i)
.getAmount() < tank.getTankCapacity(i))
return true;
}
return false;
}
public static int getRequiredAmountForItem(World world, ItemStack stack, FluidStack availableFluid) {
if (stack.getItem() == Items.GLASS_BOTTLE)
return PotionFluidHandler.getRequiredAmountForFilledBottle(stack, availableFluid);
LazyOptional<IFluidHandlerItem> capability =
stack.getCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY);
IFluidHandlerItem tank = capability.orElse(null);
if (tank == null)
return -1;
if (tank instanceof FluidBucketWrapper)
return 1000;
int filled = tank.fill(availableFluid, FluidAction.SIMULATE);
return filled == 0 ? -1 : filled;
}
public static ItemStack fillItem(World world, int requiredAmount, ItemStack stack, FluidStack availableFluid) {
FluidStack toFill = availableFluid.copy();
toFill.setAmount(requiredAmount);
availableFluid.shrink(requiredAmount);
if (stack.getItem() == Items.GLASS_BOTTLE) {
ItemStack fillBottle = ItemStack.EMPTY;
if (FluidHelper.isWater(toFill.getFluid()))
fillBottle = PotionUtils.addPotionToItemStack(new ItemStack(Items.POTION), Potions.WATER);
else
fillBottle = PotionFluidHandler.fillBottle(stack, toFill);
stack.shrink(1);
return fillBottle;
}
ItemStack split = stack.copy();
split.setCount(1);
LazyOptional<IFluidHandlerItem> capability =
split.getCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY);
IFluidHandlerItem tank = capability.orElse(null);
if (tank == null)
return ItemStack.EMPTY;
tank.fill(toFill, FluidAction.EXECUTE);
ItemStack container = tank.getContainer()
.copy();
stack.shrink(1);
return container;
}
}

View file

@ -0,0 +1,111 @@
package com.simibubi.create.content.contraptions.fluids.potion;
import java.util.Collection;
import java.util.List;
import com.simibubi.create.AllFluids;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.fluid.Fluid;
import net.minecraft.fluid.IFluidState;
import net.minecraft.item.Item;
import net.minecraft.item.Items;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.ListNBT;
import net.minecraft.potion.EffectInstance;
import net.minecraft.potion.Potion;
import net.minecraft.potion.PotionUtils;
import net.minecraft.potion.Potions;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fluids.FluidAttributes;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.ForgeFlowingFluid;
import net.minecraftforge.registries.ForgeRegistries;
public class PotionFluid extends ForgeFlowingFluid {
public enum BottleType {
REGULAR, SPLASH, LINGERING;
}
public PotionFluid(Properties properties) {
super(properties);
}
public static FluidStack withEffects(int amount, Potion potion, List<EffectInstance> customEffects) {
FluidStack fluidStack = new FluidStack(AllFluids.POTION.get()
.getStillFluid(), amount);
addPotionToFluidStack(fluidStack, potion);
appendEffects(fluidStack, customEffects);
return fluidStack;
}
@Override
public Fluid getStillFluid() {
return this;
}
@Override
public Fluid getFlowingFluid() {
return this;
}
@Override
public Item getFilledBucket() {
return Items.AIR;
}
@Override
protected BlockState getBlockState(IFluidState state) {
return Blocks.AIR.getDefaultState();
}
@Override
public boolean isSource(IFluidState p_207193_1_) {
return false;
}
@Override
public int getLevel(IFluidState p_207192_1_) {
return 0;
}
public static class PotionFluidAttributes extends FluidAttributes {
public PotionFluidAttributes(Builder builder, Fluid fluid) {
super(builder, fluid);
}
@Override
public int getColor(FluidStack stack) {
CompoundNBT tag = stack.getOrCreateTag();
int color = PotionUtils.getPotionColorFromEffectList(PotionUtils.getEffectsFromTag(tag)) | 0xff000000;
return color;
}
}
public static FluidStack addPotionToFluidStack(FluidStack fs, Potion potion) {
ResourceLocation resourcelocation = ForgeRegistries.POTION_TYPES.getKey(potion);
if (potion == Potions.EMPTY) {
fs.removeChildTag("Potion");
return fs;
}
fs.getOrCreateTag()
.putString("Potion", resourcelocation.toString());
return fs;
}
public static FluidStack appendEffects(FluidStack fs, Collection<EffectInstance> customEffects) {
if (customEffects.isEmpty())
return fs;
CompoundNBT compoundnbt = fs.getOrCreateTag();
ListNBT listnbt = compoundnbt.getList("CustomPotionEffects", 9);
for (EffectInstance effectinstance : customEffects)
listnbt.add(effectinstance.write(new CompoundNBT()));
compoundnbt.put("CustomPotionEffects", listnbt);
return fs;
}
}

View file

@ -0,0 +1,171 @@
package com.simibubi.create.content.contraptions.fluids.potion;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import com.google.common.collect.Lists;
import com.simibubi.create.content.contraptions.fluids.potion.PotionFluid.BottleType;
import com.simibubi.create.foundation.utility.NBTHelper;
import com.simibubi.create.foundation.utility.Pair;
import net.minecraft.entity.ai.attributes.AttributeModifier;
import net.minecraft.entity.ai.attributes.IAttribute;
import net.minecraft.fluid.Fluids;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.potion.Effect;
import net.minecraft.potion.EffectInstance;
import net.minecraft.potion.EffectUtils;
import net.minecraft.potion.Potion;
import net.minecraft.potion.PotionUtils;
import net.minecraft.potion.Potions;
import net.minecraft.util.IItemProvider;
import net.minecraft.util.Tuple;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.util.text.TranslationTextComponent;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fluids.FluidStack;
public class PotionFluidHandler {
public static Pair<FluidStack, ItemStack> emptyPotion(ItemStack stack, boolean simulate) {
FluidStack fluid = getFluidFromPotionItem(stack);
if (!simulate)
stack.shrink(1);
return Pair.of(fluid, new ItemStack(Items.GLASS_BOTTLE));
}
public static FluidStack getFluidFromPotionItem(ItemStack stack) {
Potion potion = PotionUtils.getPotionFromItem(stack);
List<EffectInstance> list = PotionUtils.getFullEffectsFromItem(stack);
FluidStack fluid = PotionFluid.withEffects(250, potion, list);
BottleType bottleTypeFromItem = bottleTypeFromItem(stack);
if (potion == Potions.WATER && list.isEmpty() && bottleTypeFromItem == BottleType.REGULAR)
return new FluidStack(Fluids.WATER, fluid.getAmount());
NBTHelper.writeEnum(fluid.getOrCreateTag(), "Bottle", bottleTypeFromItem);
return fluid;
}
public static BottleType bottleTypeFromItem(ItemStack stack) {
Item item = stack.getItem();
if (item == Items.LINGERING_POTION)
return BottleType.LINGERING;
if (item == Items.SPLASH_POTION)
return BottleType.SPLASH;
return BottleType.REGULAR;
}
public static IItemProvider itemFromBottleType(BottleType type) {
switch (type) {
case LINGERING:
return Items.LINGERING_POTION;
case SPLASH:
return Items.SPLASH_POTION;
case REGULAR:
default:
return Items.POTION;
}
}
public static int getRequiredAmountForFilledBottle(ItemStack stack, FluidStack availableFluid) {
return 250;
}
public static ItemStack fillBottle(ItemStack stack, FluidStack availableFluid) {
CompoundNBT tag = availableFluid.getOrCreateTag();
ItemStack potionStack = new ItemStack(itemFromBottleType(NBTHelper.readEnum(tag, "Bottle", BottleType.class)));
PotionUtils.addPotionToItemStack(potionStack, PotionUtils.getPotionTypeFromNBT(tag));
PotionUtils.appendEffects(potionStack, PotionUtils.getFullEffectsFromTag(tag));
return potionStack;
}
public static ITextComponent getPotionName(FluidStack fs) {
CompoundNBT tag = fs.getOrCreateTag();
IItemProvider itemFromBottleType = itemFromBottleType(NBTHelper.readEnum(tag, "Bottle", BottleType.class));
return new TranslationTextComponent(PotionUtils.getPotionTypeFromNBT(tag)
.getNamePrefixed(itemFromBottleType.asItem()
.getTranslationKey() + ".effect."));
}
// Modified version of PotionUtils#addPotionTooltip
@OnlyIn(Dist.CLIENT)
public static void addPotionTooltip(FluidStack fs, List<ITextComponent> tooltip, float p_185182_2_) {
List<EffectInstance> list = PotionUtils.getEffectsFromTag(fs.getOrCreateTag());
List<Tuple<String, AttributeModifier>> list1 = Lists.newArrayList();
if (list.isEmpty()) {
tooltip.add((new TranslationTextComponent("effect.none")).applyTextStyle(TextFormatting.GRAY));
} else {
for (EffectInstance effectinstance : list) {
ITextComponent itextcomponent = new TranslationTextComponent(effectinstance.getEffectName());
Effect effect = effectinstance.getPotion();
Map<IAttribute, AttributeModifier> map = effect.getAttributeModifierMap();
if (!map.isEmpty()) {
for (Entry<IAttribute, AttributeModifier> entry : map.entrySet()) {
AttributeModifier attributemodifier = entry.getValue();
AttributeModifier attributemodifier1 = new AttributeModifier(attributemodifier.getName(),
effect.getAttributeModifierAmount(effectinstance.getAmplifier(), attributemodifier),
attributemodifier.getOperation());
list1.add(new Tuple<>(entry.getKey()
.getName(), attributemodifier1));
}
}
if (effectinstance.getAmplifier() > 0) {
itextcomponent.appendText(" ")
.appendSibling(new TranslationTextComponent("potion.potency." + effectinstance.getAmplifier()));
}
if (effectinstance.getDuration() > 20) {
itextcomponent.appendText(" (")
.appendText(EffectUtils.getPotionDurationString(effectinstance, p_185182_2_))
.appendText(")");
}
tooltip.add(itextcomponent.applyTextStyle(effect.getEffectType()
.getColor()));
}
}
if (!list1.isEmpty()) {
tooltip.add(new StringTextComponent(""));
tooltip.add((new TranslationTextComponent("potion.whenDrank")).applyTextStyle(TextFormatting.DARK_PURPLE));
for (Tuple<String, AttributeModifier> tuple : list1) {
AttributeModifier attributemodifier2 = tuple.getB();
double d0 = attributemodifier2.getAmount();
double d1;
if (attributemodifier2.getOperation() != AttributeModifier.Operation.MULTIPLY_BASE
&& attributemodifier2.getOperation() != AttributeModifier.Operation.MULTIPLY_TOTAL) {
d1 = attributemodifier2.getAmount();
} else {
d1 = attributemodifier2.getAmount() * 100.0D;
}
if (d0 > 0.0D) {
tooltip.add((new TranslationTextComponent(
"attribute.modifier.plus." + attributemodifier2.getOperation()
.getId(),
ItemStack.DECIMALFORMAT.format(d1),
new TranslationTextComponent("attribute.name." + (String) tuple.getA())))
.applyTextStyle(TextFormatting.BLUE));
} else if (d0 < 0.0D) {
d1 = d1 * -1.0D;
tooltip.add((new TranslationTextComponent(
"attribute.modifier.take." + attributemodifier2.getOperation()
.getId(),
ItemStack.DECIMALFORMAT.format(d1),
new TranslationTextComponent("attribute.name." + (String) tuple.getA())))
.applyTextStyle(TextFormatting.RED));
}
}
}
}
}

View file

@ -0,0 +1,158 @@
package com.simibubi.create.content.contraptions.fluids.potion;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import com.simibubi.create.Create;
import com.simibubi.create.content.contraptions.components.mixer.MixingRecipe;
import com.simibubi.create.content.contraptions.processing.HeatCondition;
import com.simibubi.create.content.contraptions.processing.ProcessingRecipeBuilder;
import com.simibubi.create.foundation.fluid.FluidIngredient;
import net.minecraft.client.resources.ReloadListener;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.potion.Potion;
import net.minecraft.potion.PotionBrewing;
import net.minecraft.potion.PotionUtils;
import net.minecraft.potion.Potions;
import net.minecraft.profiler.IProfiler;
import net.minecraft.resources.IResourceManager;
import net.minecraftforge.common.brewing.BrewingRecipeRegistry;
import net.minecraftforge.common.brewing.IBrewingRecipe;
import net.minecraftforge.common.brewing.VanillaBrewingRecipe;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.registries.ForgeRegistries;
public class PotionMixingRecipeManager {
public static Map<Item, List<MixingRecipe>> ALL = new HashMap<>();
public static List<MixingRecipe> getAllBrewingRecipes() {
List<MixingRecipe> mixingRecipes = new ArrayList<>();
// Vanilla
for (IBrewingRecipe iBrewingRecipe : BrewingRecipeRegistry.getRecipes()) {
if (!(iBrewingRecipe instanceof VanillaBrewingRecipe))
continue;
List<ItemStack> bottles = new ArrayList<>();
PotionBrewing.POTION_ITEMS.forEach(i -> {
for (ItemStack itemStack : i.getMatchingStacks())
bottles.add(itemStack);
});
Collection<ItemStack> reagents = getAllReagents(iBrewingRecipe);
Set<ItemStack> basicPotions = new HashSet<>();
for (Potion potion : ForgeRegistries.POTION_TYPES.getValues()) {
if (potion == Potions.EMPTY)
continue;
for (ItemStack stack : bottles)
basicPotions.add(PotionUtils.addPotionToItemStack(stack.copy(), potion));
}
Set<String> uniqueKeys = new HashSet<>();
List<ItemStack> potionFrontier = new ArrayList<>();
List<ItemStack> newPotions = new ArrayList<>();
potionFrontier.addAll(basicPotions);
int recipeIndex = 0;
while (!potionFrontier.isEmpty()) {
newPotions.clear();
for (ItemStack inputPotionStack : potionFrontier) {
Potion inputPotion = PotionUtils.getPotionFromItem(inputPotionStack);
for (ItemStack potionReagent : reagents) {
ItemStack outputPotionStack = iBrewingRecipe.getOutput(inputPotionStack.copy(), potionReagent);
if (outputPotionStack.isEmpty())
continue;
String uniqueKey = potionReagent.getItem()
.getRegistryName()
.toString() + "_"
+ inputPotion.getRegistryName()
.toString()
+ "_" + inputPotionStack.getItem()
.getRegistryName()
.toString();
if (!uniqueKeys.add(uniqueKey))
continue;
if (inputPotionStack.getItem() == outputPotionStack.getItem()) {
Potion outputPotion = PotionUtils.getPotionFromItem(outputPotionStack);
if (outputPotion == Potions.WATER)
continue;
}
FluidStack fluidFromPotionItem = PotionFluidHandler.getFluidFromPotionItem(inputPotionStack);
FluidStack fluidFromPotionItem2 = PotionFluidHandler.getFluidFromPotionItem(outputPotionStack);
fluidFromPotionItem.setAmount(1000);
fluidFromPotionItem2.setAmount(1000);
MixingRecipe mixingRecipe = new ProcessingRecipeBuilder<>(MixingRecipe::new,
Create.asResource("potion_" + recipeIndex++)).require(Ingredient.fromStacks(potionReagent))
.require(FluidIngredient.fromFluidStack(fluidFromPotionItem))
.output(fluidFromPotionItem2)
.requiresHeat(HeatCondition.HEATED)
.build();
mixingRecipes.add(mixingRecipe);
newPotions.add(outputPotionStack);
}
}
potionFrontier.clear();
potionFrontier.addAll(newPotions);
}
break;
}
// TODO Modded brewing recipes?
return mixingRecipes;
}
public static Collection<ItemStack> getAllReagents(IBrewingRecipe recipe) {
return ForgeRegistries.ITEMS.getValues()
.stream()
.map(ItemStack::new)
.filter(recipe::isIngredient)
.collect(Collectors.toList());
}
public static final ReloadListener<Object> LISTENER = new ReloadListener<Object>() {
@Override
protected Object prepare(IResourceManager p_212854_1_, IProfiler p_212854_2_) {
return new Object();
}
@Override
protected void apply(Object p_212853_1_, IResourceManager p_212853_2_, IProfiler p_212853_3_) {
ALL.clear();
getAllBrewingRecipes().forEach(recipe -> {
for (Ingredient ingredient : recipe.getIngredients()) {
for (ItemStack itemStack : ingredient.getMatchingStacks()) {
ALL.computeIfAbsent(itemStack.getItem(), t -> new ArrayList<>())
.add(recipe);
return;
}
}
});
}
};
}

View file

@ -3,6 +3,7 @@ package com.simibubi.create.content.contraptions.processing;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllShapes;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.content.contraptions.fluids.actors.GenericItemFilling;
import com.simibubi.create.content.contraptions.wrench.IWrenchable;
import com.simibubi.create.foundation.advancement.AllTriggers;
import com.simibubi.create.foundation.block.ITE;
@ -81,7 +82,9 @@ public class BasinBlock extends Block implements ITE<BasinTileEntity>, IWrenchab
if (!heldItem.isEmpty()) {
if (tryEmptyItemIntoBasin(worldIn, player, handIn, heldItem, te))
return ActionResultType.SUCCESS;
return ActionResultType.PASS;
if (tryFillItemFromBasin(worldIn, player, handIn, heldItem, te))
return ActionResultType.SUCCESS;
return ActionResultType.SUCCESS;
}
IItemHandlerModifiable inv = te.itemCapability.orElse(new ItemStackHandler(1));
@ -101,25 +104,72 @@ public class BasinBlock extends Block implements ITE<BasinTileEntity>, IWrenchab
if (!EmptyingByBasin.canItemBeEmptied(worldIn, heldItem))
return false;
Pair<FluidStack, ItemStack> emptyItem = EmptyingByBasin.emptyItem(worldIn, heldItem, true);
Pair<FluidStack, ItemStack> emptyingResult = EmptyingByBasin.emptyItem(worldIn, heldItem, true);
LazyOptional<IFluidHandler> capability = te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY);
IFluidHandler tank = capability.orElse(null);
FluidStack fluidStack = emptyItem.getFirst();
FluidStack fluidStack = emptyingResult.getFirst();
if (tank == null || fluidStack.getAmount() != tank.fill(fluidStack, FluidAction.SIMULATE))
return false;
if (worldIn.isRemote)
return true;
EmptyingByBasin.emptyItem(worldIn, heldItem, false);
ItemStack copyOfHeld = heldItem.copy();
emptyingResult = EmptyingByBasin.emptyItem(worldIn, copyOfHeld, false);
tank.fill(fluidStack, FluidAction.EXECUTE);
if (heldItem.isEmpty())
player.setHeldItem(handIn, emptyItem.getSecond());
else
player.inventory.placeItemBackInInventory(worldIn, emptyItem.getSecond());
if (!player.isCreative()) {
if (copyOfHeld.isEmpty())
player.setHeldItem(handIn, emptyingResult.getSecond());
else {
player.setHeldItem(handIn, copyOfHeld);
player.inventory.placeItemBackInInventory(worldIn, emptyingResult.getSecond());
}
}
return true;
}
protected boolean tryFillItemFromBasin(World world, PlayerEntity player, Hand handIn, ItemStack heldItem,
BasinTileEntity te) {
if (!GenericItemFilling.canItemBeFilled(world, heldItem))
return false;
LazyOptional<IFluidHandler> capability = te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY);
IFluidHandler tank = capability.orElse(null);
if (tank == null)
return false;
for (int i = 0; i < tank.getTanks(); i++) {
FluidStack fluid = tank.getFluidInTank(i);
if (fluid.isEmpty())
continue;
int requiredAmountForItem = GenericItemFilling.getRequiredAmountForItem(world, heldItem, fluid.copy());
if (requiredAmountForItem == -1)
continue;
if (requiredAmountForItem > fluid.getAmount())
continue;
if (world.isRemote)
return true;
if (player.isCreative())
heldItem = heldItem.copy();
ItemStack out = GenericItemFilling.fillItem(world, requiredAmountForItem, heldItem, fluid.copy());
FluidStack copy = fluid.copy();
copy.setAmount(requiredAmountForItem);
tank.drain(copy, FluidAction.EXECUTE);
if (!player.isCreative())
player.inventory.placeItemBackInInventory(world, out);
te.notifyUpdate();
return true;
}
return false;
}
@Override
public void onLanded(IBlockReader worldIn, Entity entityIn) {
super.onLanded(worldIn, entityIn);

View file

@ -32,8 +32,23 @@ public class BasinRecipe extends ProcessingRecipe<SmartInventory> {
public static boolean match(BasinTileEntity basin, IRecipe<?> recipe) {
FilteringBehaviour filter = basin.getFilter();
if (filter == null || !filter.test(recipe.getRecipeOutput()))
if (filter == null)
return false;
boolean filterTest = filter.test(recipe.getRecipeOutput());
if (recipe instanceof BasinRecipe) {
BasinRecipe basinRecipe = (BasinRecipe) recipe;
if (basinRecipe.getRollableResults()
.isEmpty()
&& !basinRecipe.getFluidResults()
.isEmpty())
filterTest = filter.test(basinRecipe.getFluidResults()
.get(0));
}
if (!filterTest)
return false;
return apply(basin, recipe, true);
}
@ -146,17 +161,11 @@ public class BasinRecipe extends ProcessingRecipe<SmartInventory> {
return true;
}
/**
* For JEI purposes only
*/
public boolean convertedRecipe;
public static BasinRecipe convert(IRecipe<?> recipe) {
public static BasinRecipe convertShapeless(IRecipe<?> recipe) {
BasinRecipe basinRecipe =
new ProcessingRecipeBuilder<>(BasinRecipe::new, recipe.getId()).withItemIngredients(recipe.getIngredients())
.withSingleItemOutput(recipe.getRecipeOutput())
.build();
basinRecipe.convertedRecipe = true;
return basinRecipe;
}

View file

@ -4,9 +4,11 @@ import java.util.List;
import java.util.Optional;
import com.simibubi.create.AllRecipeTypes;
import com.simibubi.create.content.contraptions.fluids.potion.PotionFluidHandler;
import com.simibubi.create.foundation.utility.Pair;
import net.minecraft.item.ItemStack;
import net.minecraft.item.PotionItem;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.world.World;
import net.minecraftforge.common.util.LazyOptional;
@ -22,6 +24,9 @@ public class EmptyingByBasin {
static RecipeWrapper wrapper = new RecipeWrapper(new ItemStackHandler(1));
public static boolean canItemBeEmptied(World world, ItemStack stack) {
if (stack.getItem() instanceof PotionItem)
return true;
wrapper.setInventorySlotContents(0, stack);
if (AllRecipeTypes.EMPTYING.find(wrapper, world)
.isPresent())
@ -44,6 +49,9 @@ public class EmptyingByBasin {
FluidStack resultingFluid = FluidStack.EMPTY;
ItemStack resultingItem = ItemStack.EMPTY;
if (stack.getItem() instanceof PotionItem)
return PotionFluidHandler.emptyPotion(stack, simulate);
wrapper.setInventorySlotContents(0, stack);
Optional<IRecipe<RecipeWrapper>> recipe = AllRecipeTypes.EMPTYING.find(wrapper, world);
if (recipe.isPresent()) {

View file

@ -155,7 +155,11 @@ public class ProcessingRecipeBuilder<T extends ProcessingRecipe<?>> {
}
public ProcessingRecipeBuilder<T> output(Fluid fluid, int amount) {
params.fluidResults.add(new FluidStack(fluid, amount));
return output(new FluidStack(fluid, amount));
}
public ProcessingRecipeBuilder<T> output(FluidStack fluidStack) {
params.fluidResults.add(fluidStack);
return this;
}

View file

@ -8,6 +8,7 @@ import javax.annotation.Nonnull;
import com.simibubi.create.AllItems;
import com.simibubi.create.AllKeys;
import com.simibubi.create.content.contraptions.processing.EmptyingByBasin;
import com.simibubi.create.content.logistics.item.filter.AttributeFilterContainer.WhitelistMode;
import com.simibubi.create.foundation.item.ItemDescription;
import com.simibubi.create.foundation.utility.Lang;
@ -35,7 +36,6 @@ import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.common.util.Constants.NBT;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.fml.network.NetworkHooks;
import net.minecraftforge.items.ItemHandlerHelper;
import net.minecraftforge.items.ItemStackHandler;
@ -185,7 +185,7 @@ public class FilterItem extends Item implements INamedContainerProvider {
}
public static boolean test(World world, FluidStack stack, ItemStack filter) {
return test(world, stack, filter, false);
return test(world, stack, filter, true);
}
private static boolean test(World world, ItemStack stack, ItemStack filter, boolean matchNBT) {
@ -264,13 +264,17 @@ public class FilterItem extends Item implements INamedContainerProvider {
return false;
if (!(filter.getItem() instanceof FilterItem)) {
if (!EmptyingByBasin.canItemBeEmptied(world, filter))
return false;
FluidStack fluidInFilter = EmptyingByBasin.emptyItem(world, filter, true)
.getFirst();
if (fluidInFilter == null)
return false;
if (!matchNBT)
return filter.getCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY)
.filter(ifh -> ifh.getTanks() > 0)
.map(ifh -> ifh.getFluidInTank(0)
.getFluid() == stack.getFluid())
.orElse(false);
return stack.isFluidEqual(filter);
return fluidInFilter.getFluid()
.isEquivalentTo(stack.getFluid());
boolean fluidEqual = fluidInFilter.isFluidEqual(stack);
return fluidEqual;
}
if (AllItems.FILTER.get() == filter.getItem()) {

View file

@ -4,6 +4,7 @@ import com.simibubi.create.Create;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionHandler;
import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingPhysics;
import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.CapabilityMinecartController;
import com.simibubi.create.content.contraptions.fluids.potion.PotionMixingRecipeManager;
import com.simibubi.create.content.contraptions.wrench.WrenchItem;
import com.simibubi.create.content.schematics.ServerSchematicLoader;
import com.simibubi.create.foundation.command.AllCommands;
@ -13,6 +14,7 @@ import com.simibubi.create.foundation.utility.recipe.RecipeFinder;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.resources.IReloadableResourceManager;
import net.minecraft.world.IWorld;
import net.minecraft.world.World;
import net.minecraftforge.event.AttachCapabilitiesEvent;
@ -43,7 +45,7 @@ public class CommonEvents {
Create.lagger.tick();
ServerSpeedProvider.serverTick();
}
@SubscribeEvent
public static void onChunkUnloaded(ChunkEvent.Unload event) {
CapabilityMinecartController.onChunkUnloaded(event);
@ -74,7 +76,7 @@ public class CommonEvents {
World world = event.getWorld();
ContraptionHandler.addSpawnedContraptionsToCollisionList(entity, world);
}
@SubscribeEvent
public static void onEntityAttackedByPlayer(AttackEntityEvent event) {
WrenchItem.wrenchInstaKillsMinecarts(event);
@ -87,9 +89,10 @@ public class CommonEvents {
@SubscribeEvent
public static void serverAboutToStart(FMLServerAboutToStartEvent event) {
event.getServer()
.getResourceManager()
.addReloadListener(RecipeFinder.LISTENER);
IReloadableResourceManager resourceManager = event.getServer()
.getResourceManager();
resourceManager.addReloadListener(RecipeFinder.LISTENER);
resourceManager.addReloadListener(PotionMixingRecipeManager.LISTENER);
}
@SubscribeEvent
@ -111,7 +114,7 @@ public class CommonEvents {
Create.torquePropagator.onUnloadWorld(world);
WorldAttached.invalidateWorld(world);
}
@SubscribeEvent
public static void attachCapabilities(AttachCapabilitiesEvent<Entity> event) {
CapabilityMinecartController.attach(event);

View file

@ -4,9 +4,11 @@ import java.util.Collection;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.function.BiFunction;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import com.simibubi.create.Create;
import com.simibubi.create.CreateClient;
import com.simibubi.create.content.AllSections;
import com.simibubi.create.foundation.block.IBlockVertexColor;
@ -16,6 +18,7 @@ import com.simibubi.create.foundation.block.render.CustomRenderedItemModel;
import com.tterrag.registrate.AbstractRegistrate;
import com.tterrag.registrate.builders.BlockBuilder;
import com.tterrag.registrate.builders.Builder;
import com.tterrag.registrate.builders.FluidBuilder;
import com.tterrag.registrate.builders.ItemBuilder;
import com.tterrag.registrate.util.NonNullLazyValue;
import com.tterrag.registrate.util.entry.RegistryEntry;
@ -29,10 +32,13 @@ import net.minecraft.block.Block.Properties;
import net.minecraft.client.renderer.color.IBlockColor;
import net.minecraft.client.renderer.color.IItemColor;
import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.fluid.Fluid;
import net.minecraft.item.Item;
import net.minecraft.util.IItemProvider;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fluids.FluidAttributes;
import net.minecraftforge.fluids.ForgeFlowingFluid;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.RegistryObject;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
@ -114,11 +120,24 @@ public class CreateRegistrate extends AbstractRegistrate<CreateRegistrate> {
.simpleItem();
}
/* Fluids */
public <T extends ForgeFlowingFluid> FluidBuilder<T, CreateRegistrate> virtualFluid(String name,
BiFunction<FluidAttributes.Builder, Fluid, FluidAttributes> attributesFactory,
NonNullFunction<ForgeFlowingFluid.Properties, T> factory) {
return entry(name,
c -> new VirtualFluidBuilder<>(self(), self(), name, c, Create.asResource("fluid/" + name + "_still"),
Create.asResource("fluid/" + name + "_flow"), attributesFactory, factory));
}
/* Util */
public static <T extends Block> NonNullConsumer<? super T> connectedTextures(ConnectedTextureBehaviour behavior) {
return entry -> onClient(() -> () -> registerCTBehviour(entry, behavior));
}
public static <T extends Block> NonNullConsumer<? super T> blockModel(Supplier<NonNullFunction<IBakedModel, ? extends IBakedModel>> func) {
public static <T extends Block> NonNullConsumer<? super T> blockModel(
Supplier<NonNullFunction<IBakedModel, ? extends IBakedModel>> func) {
return entry -> onClient(() -> () -> registerBlockModel(entry, func));
}

View file

@ -0,0 +1,35 @@
package com.simibubi.create.foundation.data;
import java.util.function.BiFunction;
import com.tterrag.registrate.AbstractRegistrate;
import com.tterrag.registrate.builders.BuilderCallback;
import com.tterrag.registrate.builders.FluidBuilder;
import com.tterrag.registrate.util.nullness.NonNullFunction;
import com.tterrag.registrate.util.nullness.NonNullSupplier;
import net.minecraft.fluid.Fluid;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fluids.FluidAttributes;
import net.minecraftforge.fluids.ForgeFlowingFluid;
import net.minecraftforge.fluids.ForgeFlowingFluid.Properties;
/**
* For registering fluids with no buckets/blocks
*/
public class VirtualFluidBuilder<T extends ForgeFlowingFluid, P> extends FluidBuilder<T, P> {
public VirtualFluidBuilder(AbstractRegistrate<?> owner, P parent, String name, BuilderCallback callback,
ResourceLocation stillTexture, ResourceLocation flowingTexture,
BiFunction<FluidAttributes.Builder, Fluid, FluidAttributes> attributesFactory,
NonNullFunction<Properties, T> factory) {
super(owner, parent, name, callback, stillTexture, flowingTexture, attributesFactory, factory);
source(factory);
}
@Override
public NonNullSupplier<T> asSupplier() {
return this::getEntry;
}
}

View file

@ -3,23 +3,21 @@ package com.simibubi.create.foundation.data.recipe;
import com.simibubi.create.AllRecipeTypes;
import net.minecraft.data.DataGenerator;
import net.minecraft.fluid.Fluids;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.potion.PotionUtils;
import net.minecraft.potion.Potions;
import net.minecraftforge.common.crafting.NBTIngredient;
public class EmptyingRecipeGen extends ProcessingRecipeGen {
GeneratedRecipe
WATER_BOTTLE = create("water_bottle", b -> b
.require(NBTIngredient.fromStacks(PotionUtils.addPotionToItemStack(new ItemStack(Items.POTION), Potions.WATER)))
.output(Fluids.WATER, 250)
.output(Items.GLASS_BOTTLE))
;
/*
* potion/bottles are handled internally now. keeping this builder for reference
*/
// GeneratedRecipe
//
// WATER_BOTTLE = create("water_bottle", b -> b
// .require(NBTIngredient.fromStacks(PotionUtils.addPotionToItemStack(new ItemStack(Items.POTION), Potions.WATER)))
// .output(Fluids.WATER, 250)
// .output(Items.GLASS_BOTTLE))
//
// ;
public EmptyingRecipeGen(DataGenerator p_i48262_1_) {
super(p_i48262_1_);

View file

@ -3,21 +3,20 @@ package com.simibubi.create.foundation.data.recipe;
import com.simibubi.create.AllRecipeTypes;
import net.minecraft.data.DataGenerator;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.potion.PotionUtils;
import net.minecraft.potion.Potions;
import net.minecraft.tags.FluidTags;
public class FillingRecipeGen extends ProcessingRecipeGen {
GeneratedRecipe
/*
* potion/bottles are handled internally now. keeping this builder for reference
*/
WATER_BOTTLE = create("water_bottle", b -> b.require(Items.GLASS_BOTTLE)
.require(FluidTags.WATER, 250)
.output(PotionUtils.addPotionToItemStack(new ItemStack(Items.POTION), Potions.WATER)))
;
// GeneratedRecipe
//
// WATER_BOTTLE = create("water_bottle", b -> b.require(Items.GLASS_BOTTLE)
// .require(FluidTags.WATER, 250)
// .output(PotionUtils.addPotionToItemStack(new ItemStack(Items.POTION), Potions.WATER)))
//
// ;
public FillingRecipeGen(DataGenerator p_i48262_1_) {
super(p_i48262_1_);

View file

@ -9,7 +9,6 @@ import net.minecraft.block.Blocks;
import net.minecraft.data.DataGenerator;
import net.minecraft.fluid.Fluids;
import net.minecraft.item.Items;
import net.minecraft.tags.FluidTags;
import net.minecraft.tags.ItemTags;
import net.minecraftforge.common.Tags;
@ -17,8 +16,8 @@ public class MixingRecipeGen extends ProcessingRecipeGen {
GeneratedRecipe
TEMPCOBBLE = create("temp_cobble", b -> b.require(FluidTags.WATER, 250)
.require(FluidTags.LAVA, 25)
TEMPCOBBLE = create("temp_cobble", b -> b.require(Fluids.WATER, 250)
.require(Fluids.LAVA, 25)
.output(Blocks.COBBLESTONE, 1)),
TEMP_LAVA = create("temp_lava", b -> b.require(Tags.Items.COBBLESTONE)

View file

@ -1,5 +1,7 @@
package com.simibubi.create.foundation.fluid;
import com.simibubi.create.foundation.utility.Iterate;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.items.wrapper.EmptyHandler;
@ -64,23 +66,29 @@ public class CombinedTankWrapper implements IFluidHandler {
public int fill(FluidStack resource, FluidAction action) {
if (resource.isEmpty())
return 0;
int filled = 0;
resource = resource.copy();
for (IFluidHandler iFluidHandler : itemHandler) {
boolean skipRest = false;
int filledIntoCurrent = iFluidHandler.fill(resource, action);
for (int i = 0; i < iFluidHandler.getTanks(); i++)
if (iFluidHandler.getFluidInTank(i).isFluidEqual(resource) && enforceVariety)
skipRest = true;
resource.shrink(filledIntoCurrent);
filled += filledIntoCurrent;
boolean fittingHandlerFound = false;
Outer: for (boolean searchPass : Iterate.trueAndFalse) {
for (IFluidHandler iFluidHandler : itemHandler) {
if (resource.isEmpty() || skipRest)
break;
for (int i = 0; i < iFluidHandler.getTanks(); i++)
if (searchPass && iFluidHandler.getFluidInTank(i)
.isFluidEqual(resource))
fittingHandlerFound = true;
if (searchPass && !fittingHandlerFound)
continue;
int filledIntoCurrent = iFluidHandler.fill(resource, action);
resource.shrink(filledIntoCurrent);
filled += filledIntoCurrent;
if (resource.isEmpty() || fittingHandlerFound || enforceVariety && filledIntoCurrent != 0)
break Outer;
}
}
return filled;
@ -90,7 +98,7 @@ public class CombinedTankWrapper implements IFluidHandler {
public FluidStack drain(FluidStack resource, FluidAction action) {
if (resource.isEmpty())
return resource;
FluidStack drained = FluidStack.EMPTY;
resource = resource.copy();
@ -99,8 +107,8 @@ public class CombinedTankWrapper implements IFluidHandler {
int amount = drainedFromCurrent.getAmount();
resource.shrink(amount);
if (!drainedFromCurrent.isEmpty())
drained = new FluidStack(drainedFromCurrent.getFluid(), amount + drained.getAmount());
if (!drainedFromCurrent.isEmpty() && (drained.isEmpty() || drainedFromCurrent.isFluidEqual(drained)))
drained = new FluidStack(drainedFromCurrent.getFluid(), amount + drained.getAmount(), drained.getTag());
if (resource.isEmpty())
break;
}
@ -117,8 +125,9 @@ public class CombinedTankWrapper implements IFluidHandler {
int amount = drainedFromCurrent.getAmount();
maxDrain -= amount;
if (!drainedFromCurrent.isEmpty())
drained = new FluidStack(drainedFromCurrent.getFluid(), amount + drained.getAmount());
if (!drainedFromCurrent.isEmpty() && (drained.isEmpty() || drainedFromCurrent.isFluidEqual(drained)))
drained = new FluidStack(drainedFromCurrent.getFluid(), amount + drained.getAmount(),
drainedFromCurrent.getTag());
if (maxDrain == 0)
break;
}

View file

@ -42,6 +42,15 @@ public abstract class FluidIngredient implements Predicate<FluidStack> {
return ingredient;
}
public static FluidIngredient fromFluidStack(FluidStack fluidStack) {
FluidStackIngredient ingredient = new FluidStackIngredient();
ingredient.fluid = fluidStack.getFluid();
ingredient.amountRequired = fluidStack.getAmount();
if (fluidStack.hasTag())
ingredient.tagToMatch = fluidStack.getTag();
return ingredient;
}
protected int amountRequired;
protected abstract boolean testInternal(FluidStack t);
@ -135,10 +144,12 @@ public abstract class FluidIngredient implements Predicate<FluidStack> {
if (!t.getFluid()
.isEquivalentTo(fluid))
return false;
CompoundNBT tag = t.getTag()
.copy();
return tag.merge(tagToMatch)
.equals(t.getTag());
if (tagToMatch.isEmpty())
return true;
CompoundNBT tag = t.getOrCreateTag();
return tag.copy()
.merge(tagToMatch)
.equals(tag);
}
@Override

View file

@ -13,4 +13,7 @@ public net.minecraft.world.server.ChunkManager field_219253_g #chunksToUnload
# ChunkStatus
public-f net.minecraft.world.chunk.ChunkStatus field_222617_m #FULL
public net.minecraft.world.chunk.ChunkStatus$IGenerationWorker
public net.minecraft.world.chunk.ChunkStatus$ILoadingWorker
public net.minecraft.world.chunk.ChunkStatus$ILoadingWorker
# PotionBrewing
public net.minecraft.potion.PotionBrewing field_185215_c # POTION_ITEMS

View file

@ -14,31 +14,31 @@
"create.recipe.crushing": "Crushing",
"create.recipe.milling": "Milling",
"create.recipe.splashing": "Bulk Washing",
"create.recipe.splashing.fan": "Fan behind Flowing Water",
"create.recipe.smoking_via_fan": "Bulk Smoking",
"create.recipe.smoking_via_fan.fan": "Fan behind Fire",
"create.recipe.blasting_via_fan": "Bulk Smelting",
"create.recipe.blasting_via_fan.fan": "Fan behind Lava",
"create.recipe.fan_washing": "Bulk Washing",
"create.recipe.fan_washing.fan": "Fan behind Flowing Water",
"create.recipe.fan_smoking": "Bulk Smoking",
"create.recipe.fan_smoking.fan": "Fan behind Fire",
"create.recipe.fan_blasting": "Bulk Blasting",
"create.recipe.fan_blasting.fan": "Fan behind Lava",
"create.recipe.pressing": "Pressing",
"create.recipe.mixing": "Mixing",
"create.recipe.shapeless_mixing": "Shapeless Crafting",
"create.recipe.automatic_shapeless": "Automated Shapeless Crafting",
"create.recipe.automatic_brewing": "Automated Brewing",
"create.recipe.packing": "Compacting",
"create.recipe.automatic_packing": "Automated Packing",
"create.recipe.sawing": "Sawing",
"create.recipe.mechanical_crafting": "Crafting",
"create.recipe.mechanical_crafting_exclusive": "Mechanical Crafting",
"create.recipe.mechanical_crafting": "Mechanical Crafting",
"create.recipe.automatic_shaped": "Automated Shaped Crafting",
"create.recipe.block_cutting": "Block Cutting",
"create.recipe.blockzapper_upgrade": "Handheld Blockzapper",
"create.recipe.sandpaper_polishing": "Sandpaper Polishing",
"create.recipe.mystery_conversion": "Chromatic Metamorphosis",
"create.recipe.processing.catalyst": "Catalyst",
"create.recipe.processing.chance": "%1$s%% Chance",
"create.recipe.processing.chanceToReturn": "%1$s%% Chance to Return",
"create.recipe.mystery_conversion": "Mysterious Conversion",
"create.recipe.processing.chance": "%1$s%% Chance",
"create.recipe.heat_requirement.none": "No Heating Required",
"create.recipe.heat_requirement.heated": "Heated",
"create.recipe.heat_requirement.superheated": "Super-Heated",
"create.generic.range": "Range",
"create.generic.radius": "Radius",
"create.generic.width": "Width",
@ -52,7 +52,6 @@
"create.generic.unit.rpm": "RPM",
"create.generic.unit.stress": "su",
"create.generic.unit.degrees": "\u00B0",
"create.generic.unit.bucket": "1 Bucket",
"create.generic.unit.millibuckets": "%1$smB",
"create.action.scroll": "Scroll",

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

View file

@ -0,0 +1,3 @@
{
"animation": {}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

View file

@ -0,0 +1,5 @@
{
"animation": {
"frametime": 1
}
}