CreateMod/src/main/java/com/simibubi/create/compat/jei/CreateJEI.java
zelophed 25f259e0bc Pondering Alone, Part V
- merge mc1.18/dev
- reuse transform interfaces from Flywheel and include them in catnip
- extend SBB interface slightly
- copy .editorconfig to catnip and ponder
2022-10-14 00:15:44 +02:00

574 lines
23 KiB
Java

package com.simibubi.create.compat.jei;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllFluids;
import com.simibubi.create.AllItems;
import com.simibubi.create.AllRecipeTypes;
import com.simibubi.create.Create;
import com.simibubi.create.compat.jei.category.BlockCuttingCategory;
import com.simibubi.create.compat.jei.category.BlockCuttingCategory.CondensedBlockCuttingRecipe;
import com.simibubi.create.compat.jei.category.CreateRecipeCategory;
import com.simibubi.create.compat.jei.category.CrushingCategory;
import com.simibubi.create.compat.jei.category.DeployingCategory;
import com.simibubi.create.compat.jei.category.FanBlastingCategory;
import com.simibubi.create.compat.jei.category.FanHauntingCategory;
import com.simibubi.create.compat.jei.category.FanSmokingCategory;
import com.simibubi.create.compat.jei.category.FanWashingCategory;
import com.simibubi.create.compat.jei.category.ItemApplicationCategory;
import com.simibubi.create.compat.jei.category.ItemDrainCategory;
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.compat.jei.category.SequencedAssemblyCategory;
import com.simibubi.create.compat.jei.category.SpoutCategory;
import com.simibubi.create.content.contraptions.components.crafter.MechanicalCraftingRecipe;
import com.simibubi.create.content.contraptions.components.crusher.AbstractCrushingRecipe;
import com.simibubi.create.content.contraptions.components.deployer.DeployerApplicationRecipe;
import com.simibubi.create.content.contraptions.components.deployer.ManualApplicationRecipe;
import com.simibubi.create.content.contraptions.components.fan.HauntingRecipe;
import com.simibubi.create.content.contraptions.components.fan.SplashingRecipe;
import com.simibubi.create.content.contraptions.components.press.MechanicalPressTileEntity;
import com.simibubi.create.content.contraptions.components.press.PressingRecipe;
import com.simibubi.create.content.contraptions.components.saw.CuttingRecipe;
import com.simibubi.create.content.contraptions.components.saw.SawTileEntity;
import com.simibubi.create.content.contraptions.fluids.actors.FillingRecipe;
import com.simibubi.create.content.contraptions.fluids.potion.PotionFluid;
import com.simibubi.create.content.contraptions.fluids.recipe.PotionMixingRecipes;
import com.simibubi.create.content.contraptions.itemAssembly.SequencedAssemblyRecipe;
import com.simibubi.create.content.contraptions.processing.BasinRecipe;
import com.simibubi.create.content.contraptions.processing.EmptyingRecipe;
import com.simibubi.create.content.contraptions.processing.ItemApplicationRecipe;
import com.simibubi.create.content.curiosities.tools.BlueprintScreen;
import com.simibubi.create.content.curiosities.tools.SandPaperPolishingRecipe;
import com.simibubi.create.content.logistics.item.LinkedControllerScreen;
import com.simibubi.create.content.logistics.item.filter.AbstractFilterScreen;
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleScreen;
import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.config.CRecipes;
import com.simibubi.create.foundation.data.recipe.LogStrippingFakeRecipes;
import com.simibubi.create.foundation.gui.container.AbstractSimiContainerScreen;
import com.simibubi.create.foundation.utility.CreateLang;
import com.simibubi.create.foundation.utility.recipe.IRecipeTypeInfo;
import mezz.jei.api.IModPlugin;
import mezz.jei.api.JeiPlugin;
import mezz.jei.api.constants.RecipeTypes;
import mezz.jei.api.forge.ForgeTypes;
import mezz.jei.api.gui.drawable.IDrawable;
import mezz.jei.api.recipe.category.IRecipeCategory;
import mezz.jei.api.registration.IGuiHandlerRegistration;
import mezz.jei.api.registration.IRecipeCatalystRegistration;
import mezz.jei.api.registration.IRecipeCategoryRegistration;
import mezz.jei.api.registration.IRecipeRegistration;
import mezz.jei.api.registration.IRecipeTransferRegistration;
import mezz.jei.api.registration.ISubtypeRegistration;
import mezz.jei.api.runtime.IIngredientManager;
import net.createmod.catnip.config.ConfigBase.ConfigBool;
import net.minecraft.client.Minecraft;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.crafting.AbstractCookingRecipe;
import net.minecraft.world.item.crafting.CraftingRecipe;
import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.item.crafting.RecipeType;
import net.minecraft.world.item.crafting.SmokingRecipe;
import net.minecraft.world.level.ItemLike;
import net.minecraft.world.level.block.Blocks;
import net.minecraftforge.common.crafting.IShapedRecipe;
import net.minecraftforge.fml.ModList;
@JeiPlugin
@SuppressWarnings("unused")
@ParametersAreNonnullByDefault
public class CreateJEI implements IModPlugin {
private static final ResourceLocation ID = Create.asResource("jei_plugin");
private final List<CreateRecipeCategory<?>> allCategories = new ArrayList<>();
private IIngredientManager ingredientManager;
private void loadCategories() {
allCategories.clear();
CreateRecipeCategory<?>
milling = builder(AbstractCrushingRecipe.class)
.addTypedRecipes(AllRecipeTypes.MILLING)
.catalyst(AllBlocks.MILLSTONE::get)
.doubleItemIcon(AllBlocks.MILLSTONE.get(), AllItems.WHEAT_FLOUR.get())
.emptyBackground(177, 53)
.build("milling", MillingCategory::new),
crushing = builder(AbstractCrushingRecipe.class)
.addTypedRecipes(AllRecipeTypes.CRUSHING)
.addTypedRecipesExcluding(AllRecipeTypes.MILLING::getType, AllRecipeTypes.CRUSHING::getType)
.catalyst(AllBlocks.CRUSHING_WHEEL::get)
.doubleItemIcon(AllBlocks.CRUSHING_WHEEL.get(), AllItems.CRUSHED_GOLD.get())
.emptyBackground(177, 100)
.build("crushing", CrushingCategory::new),
pressing = builder(PressingRecipe.class)
.addTypedRecipes(AllRecipeTypes.PRESSING)
.catalyst(AllBlocks.MECHANICAL_PRESS::get)
.doubleItemIcon(AllBlocks.MECHANICAL_PRESS.get(), AllItems.IRON_SHEET.get())
.emptyBackground(177, 70)
.build("pressing", PressingCategory::new),
washing = builder(SplashingRecipe.class)
.addTypedRecipes(AllRecipeTypes.SPLASHING)
.catalystStack(ProcessingViaFanCategory.getFan("fan_washing"))
.doubleItemIcon(AllItems.PROPELLER.get(), Items.WATER_BUCKET)
.emptyBackground(178, 72)
.build("fan_washing", FanWashingCategory::new),
smoking = builder(SmokingRecipe.class)
.addTypedRecipes(() -> RecipeType.SMOKING)
.catalystStack(ProcessingViaFanCategory.getFan("fan_smoking"))
.doubleItemIcon(AllItems.PROPELLER.get(), Items.CAMPFIRE)
.emptyBackground(178, 72)
.build("fan_smoking", FanSmokingCategory::new),
blasting = builder(AbstractCookingRecipe.class)
.addTypedRecipesExcluding(() -> RecipeType.SMELTING, () -> RecipeType.BLASTING)
.addTypedRecipes(() -> RecipeType.BLASTING)
.removeRecipes(() -> RecipeType.SMOKING)
.catalystStack(ProcessingViaFanCategory.getFan("fan_blasting"))
.doubleItemIcon(AllItems.PROPELLER.get(), Items.LAVA_BUCKET)
.emptyBackground(178, 72)
.build("fan_blasting", FanBlastingCategory::new),
haunting = builder(HauntingRecipe.class)
.addTypedRecipes(AllRecipeTypes.HAUNTING)
.catalystStack(ProcessingViaFanCategory.getFan("fan_haunting"))
.doubleItemIcon(AllItems.PROPELLER.get(), Items.SOUL_CAMPFIRE)
.emptyBackground(178, 72)
.build("fan_haunting", FanHauntingCategory::new),
mixing = builder(BasinRecipe.class)
.addTypedRecipes(AllRecipeTypes.MIXING)
.catalyst(AllBlocks.MECHANICAL_MIXER::get)
.catalyst(AllBlocks.BASIN::get)
.doubleItemIcon(AllBlocks.MECHANICAL_MIXER.get(), AllBlocks.BASIN.get())
.emptyBackground(177, 103)
.build("mixing", MixingCategory::standard),
autoShapeless = builder(BasinRecipe.class)
.enableWhen(c -> c.allowShapelessInMixer)
.addAllRecipesIf(r -> r instanceof CraftingRecipe && !(r instanceof IShapedRecipe<?>)
&& r.getIngredients()
.size() > 1
&& !MechanicalPressTileEntity.canCompress(r) && !AllRecipeTypes.shouldIgnoreInAutomation(r),
BasinRecipe::convertShapeless)
.catalyst(AllBlocks.MECHANICAL_MIXER::get)
.catalyst(AllBlocks.BASIN::get)
.doubleItemIcon(AllBlocks.MECHANICAL_MIXER.get(), Items.CRAFTING_TABLE)
.emptyBackground(177, 85)
.build("automatic_shapeless", MixingCategory::autoShapeless),
brewing = builder(BasinRecipe.class)
.enableWhen(c -> c.allowBrewingInMixer)
.addRecipes(() -> PotionMixingRecipes.ALL)
.catalyst(AllBlocks.MECHANICAL_MIXER::get)
.catalyst(AllBlocks.BASIN::get)
.doubleItemIcon(AllBlocks.MECHANICAL_MIXER.get(), Blocks.BREWING_STAND)
.emptyBackground(177, 103)
.build("automatic_brewing", MixingCategory::autoBrewing),
packing = builder(BasinRecipe.class)
.addTypedRecipes(AllRecipeTypes.COMPACTING)
.catalyst(AllBlocks.MECHANICAL_PRESS::get)
.catalyst(AllBlocks.BASIN::get)
.doubleItemIcon(AllBlocks.MECHANICAL_PRESS.get(), AllBlocks.BASIN.get())
.emptyBackground(177, 103)
.build("packing", PackingCategory::standard),
autoSquare = builder(BasinRecipe.class)
.enableWhen(c -> c.allowShapedSquareInPress)
.addAllRecipesIf(
r -> (r instanceof CraftingRecipe) && !(r instanceof MechanicalCraftingRecipe)
&& MechanicalPressTileEntity.canCompress(r) && !AllRecipeTypes.shouldIgnoreInAutomation(r),
BasinRecipe::convertShapeless)
.catalyst(AllBlocks.MECHANICAL_PRESS::get)
.catalyst(AllBlocks.BASIN::get)
.doubleItemIcon(AllBlocks.MECHANICAL_PRESS.get(), Blocks.CRAFTING_TABLE)
.emptyBackground(177, 85)
.build("automatic_packing", PackingCategory::autoSquare),
sawing = builder(CuttingRecipe.class)
.addTypedRecipes(AllRecipeTypes.CUTTING)
.catalyst(AllBlocks.MECHANICAL_SAW::get)
.doubleItemIcon(AllBlocks.MECHANICAL_SAW.get(), Items.OAK_LOG)
.emptyBackground(177, 70)
.build("sawing", SawingCategory::new),
blockCutting = builder(CondensedBlockCuttingRecipe.class)
.enableWhen(c -> c.allowStonecuttingOnSaw)
.addRecipes(() -> CondensedBlockCuttingRecipe.condenseRecipes(getTypedRecipesExcluding(RecipeType.STONECUTTING, AllRecipeTypes::shouldIgnoreInAutomation)))
.catalyst(AllBlocks.MECHANICAL_SAW::get)
.doubleItemIcon(AllBlocks.MECHANICAL_SAW.get(), Items.STONE_BRICK_STAIRS)
.emptyBackground(177, 70)
.build("block_cutting", BlockCuttingCategory::new),
woodCutting = builder(CondensedBlockCuttingRecipe.class)
.enableIf(c -> c.allowWoodcuttingOnSaw.get() && ModList.get()
.isLoaded("druidcraft"))
.addRecipes(() -> CondensedBlockCuttingRecipe.condenseRecipes(getTypedRecipesExcluding(SawTileEntity.woodcuttingRecipeType.get(), AllRecipeTypes::shouldIgnoreInAutomation)))
.catalyst(AllBlocks.MECHANICAL_SAW::get)
.doubleItemIcon(AllBlocks.MECHANICAL_SAW.get(), Items.OAK_STAIRS)
.emptyBackground(177, 70)
.build("wood_cutting", BlockCuttingCategory::new),
polishing = builder(SandPaperPolishingRecipe.class)
.addTypedRecipes(AllRecipeTypes.SANDPAPER_POLISHING)
.catalyst(AllItems.SAND_PAPER::get)
.catalyst(AllItems.RED_SAND_PAPER::get)
.itemIcon(AllItems.SAND_PAPER.get())
.emptyBackground(177, 55)
.build("sandpaper_polishing", PolishingCategory::new),
item_application = builder(ItemApplicationRecipe.class)
.addTypedRecipes(AllRecipeTypes.ITEM_APPLICATION)
.addRecipes(LogStrippingFakeRecipes::createRecipes)
.itemIcon(AllItems.BRASS_HAND.get())
.emptyBackground(177, 60)
.build("item_application", ItemApplicationCategory::new),
deploying = builder(DeployerApplicationRecipe.class)
.addTypedRecipes(AllRecipeTypes.DEPLOYING)
.addTypedRecipes(AllRecipeTypes.SANDPAPER_POLISHING::getType, DeployerApplicationRecipe::convert)
.addTypedRecipes(AllRecipeTypes.ITEM_APPLICATION::getType, ManualApplicationRecipe::asDeploying)
.catalyst(AllBlocks.DEPLOYER::get)
.catalyst(AllBlocks.DEPOT::get)
.catalyst(AllItems.BELT_CONNECTOR::get)
.itemIcon(AllBlocks.DEPLOYER.get())
.emptyBackground(177, 70)
.build("deploying", DeployingCategory::new),
spoutFilling = builder(FillingRecipe.class)
.addTypedRecipes(AllRecipeTypes.FILLING)
.addRecipeListConsumer(recipes -> SpoutCategory.consumeRecipes(recipes::add, ingredientManager))
.catalyst(AllBlocks.SPOUT::get)
.doubleItemIcon(AllBlocks.SPOUT.get(), Items.WATER_BUCKET)
.emptyBackground(177, 70)
.build("spout_filling", SpoutCategory::new),
draining = builder(EmptyingRecipe.class)
.addRecipeListConsumer(recipes -> ItemDrainCategory.consumeRecipes(recipes::add, ingredientManager))
.addTypedRecipes(AllRecipeTypes.EMPTYING)
.catalyst(AllBlocks.ITEM_DRAIN::get)
.doubleItemIcon(AllBlocks.ITEM_DRAIN.get(), Items.WATER_BUCKET)
.emptyBackground(177, 50)
.build("draining", ItemDrainCategory::new),
autoShaped = builder(CraftingRecipe.class)
.enableWhen(c -> c.allowRegularCraftingInCrafter)
.addAllRecipesIf(r -> r instanceof CraftingRecipe && !(r instanceof IShapedRecipe<?>)
&& r.getIngredients()
.size() == 1
&& !AllRecipeTypes.shouldIgnoreInAutomation(r))
.addTypedRecipesIf(() -> RecipeType.CRAFTING,
recipe -> recipe instanceof IShapedRecipe<?> && !AllRecipeTypes.shouldIgnoreInAutomation(recipe))
.catalyst(AllBlocks.MECHANICAL_CRAFTER::get)
.itemIcon(AllBlocks.MECHANICAL_CRAFTER.get())
.emptyBackground(177, 107)
.build("automatic_shaped", MechanicalCraftingCategory::new),
mechanicalCrafting = builder(CraftingRecipe.class)
.addTypedRecipes(AllRecipeTypes.MECHANICAL_CRAFTING)
.catalyst(AllBlocks.MECHANICAL_CRAFTER::get)
.itemIcon(AllBlocks.MECHANICAL_CRAFTER.get())
.emptyBackground(177, 107)
.build("mechanical_crafting", MechanicalCraftingCategory::new),
seqAssembly = builder(SequencedAssemblyRecipe.class)
.addTypedRecipes(AllRecipeTypes.SEQUENCED_ASSEMBLY)
.itemIcon(AllItems.PRECISION_MECHANISM.get())
.emptyBackground(180, 115)
.build("sequenced_assembly", SequencedAssemblyCategory::new),
mysteryConversion = builder(ConversionRecipe.class)
.addRecipes(() -> MysteriousItemConversionCategory.RECIPES)
.itemIcon(AllBlocks.PECULIAR_BELL.get())
.emptyBackground(177, 50)
.build("mystery_conversion", MysteriousItemConversionCategory::new);
}
private <T extends Recipe<?>> CategoryBuilder<T> builder(Class<? extends T> recipeClass) {
return new CategoryBuilder<>(recipeClass);
}
@Override
@Nonnull
public ResourceLocation getPluginUid() {
return ID;
}
@Override
public void registerCategories(IRecipeCategoryRegistration registration) {
loadCategories();
registration.addRecipeCategories(allCategories.toArray(IRecipeCategory[]::new));
}
@Override
public void registerRecipes(IRecipeRegistration registration) {
ingredientManager = registration.getIngredientManager();
allCategories.forEach(c -> c.registerRecipes(registration));
registration.addRecipes(RecipeTypes.CRAFTING, ToolboxColoringRecipeMaker.createRecipes().toList());
}
@Override
public void registerRecipeCatalysts(IRecipeCatalystRegistration registration) {
allCategories.forEach(c -> c.registerCatalysts(registration));
}
@Override
public void registerRecipeTransferHandlers(IRecipeTransferRegistration registration) {
registration.addRecipeTransferHandler(new BlueprintTransferHandler(), RecipeTypes.CRAFTING);
}
@Override
public void registerFluidSubtypes(ISubtypeRegistration registration) {
PotionFluidSubtypeInterpreter interpreter = new PotionFluidSubtypeInterpreter();
PotionFluid potionFluid = AllFluids.POTION.get();
registration.registerSubtypeInterpreter(ForgeTypes.FLUID_STACK, potionFluid.getSource(), interpreter);
registration.registerSubtypeInterpreter(ForgeTypes.FLUID_STACK, potionFluid.getFlowing(), interpreter);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public void registerGuiHandlers(IGuiHandlerRegistration registration) {
registration.addGenericGuiContainerHandler(AbstractSimiContainerScreen.class, new SlotMover());
registration.addGhostIngredientHandler(AbstractFilterScreen.class, new GhostIngredientHandler());
registration.addGhostIngredientHandler(BlueprintScreen.class, new GhostIngredientHandler());
registration.addGhostIngredientHandler(LinkedControllerScreen.class, new GhostIngredientHandler());
registration.addGhostIngredientHandler(ScheduleScreen.class, new GhostIngredientHandler());
}
private class CategoryBuilder<T extends Recipe<?>> {
private final Class<? extends T> recipeClass;
private Predicate<CRecipes> predicate = cRecipes -> true;
private IDrawable background;
private IDrawable icon;
private final List<Consumer<List<T>>> recipeListConsumers = new ArrayList<>();
private final List<Supplier<? extends ItemStack>> catalysts = new ArrayList<>();
public CategoryBuilder(Class<? extends T> recipeClass) {
this.recipeClass = recipeClass;
}
public CategoryBuilder<T> enableIf(Predicate<CRecipes> predicate) {
this.predicate = predicate;
return this;
}
public CategoryBuilder<T> enableWhen(Function<CRecipes, ConfigBool> configValue) {
predicate = c -> configValue.apply(c).get();
return this;
}
public CategoryBuilder<T> addRecipeListConsumer(Consumer<List<T>> consumer) {
recipeListConsumers.add(consumer);
return this;
}
public CategoryBuilder<T> addRecipes(Supplier<Collection<? extends T>> collection) {
return addRecipeListConsumer(recipes -> recipes.addAll(collection.get()));
}
public CategoryBuilder<T> addAllRecipesIf(Predicate<Recipe<?>> pred) {
return addRecipeListConsumer(recipes -> consumeAllRecipes(recipe -> {
if (pred.test(recipe)) {
recipes.add((T) recipe);
}
}));
}
public CategoryBuilder<T> addAllRecipesIf(Predicate<Recipe<?>> pred, Function<Recipe<?>, T> converter) {
return addRecipeListConsumer(recipes -> consumeAllRecipes(recipe -> {
if (pred.test(recipe)) {
recipes.add(converter.apply(recipe));
}
}));
}
public CategoryBuilder<T> addTypedRecipes(IRecipeTypeInfo recipeTypeEntry) {
return addTypedRecipes(recipeTypeEntry::getType);
}
public CategoryBuilder<T> addTypedRecipes(Supplier<RecipeType<? extends T>> recipeType) {
return addRecipeListConsumer(recipes -> CreateJEI.<T>consumeTypedRecipes(recipes::add, recipeType.get()));
}
public CategoryBuilder<T> addTypedRecipes(Supplier<RecipeType<? extends T>> recipeType, Function<Recipe<?>, T> converter) {
return addRecipeListConsumer(recipes -> CreateJEI.<T>consumeTypedRecipes(recipe -> recipes.add(converter.apply(recipe)), recipeType.get()));
}
public CategoryBuilder<T> addTypedRecipesIf(Supplier<RecipeType<? extends T>> recipeType, Predicate<Recipe<?>> pred) {
return addRecipeListConsumer(recipes -> CreateJEI.<T>consumeTypedRecipes(recipe -> {
if (pred.test(recipe)) {
recipes.add(recipe);
}
}, recipeType.get()));
}
public CategoryBuilder<T> addTypedRecipesExcluding(Supplier<RecipeType<? extends T>> recipeType,
Supplier<RecipeType<? extends T>> excluded) {
return addRecipeListConsumer(recipes -> {
List<Recipe<?>> excludedRecipes = getTypedRecipes(excluded.get());
CreateJEI.<T>consumeTypedRecipes(recipe -> {
for (Recipe<?> excludedRecipe : excludedRecipes) {
if (doInputsMatch(recipe, excludedRecipe)) {
return;
}
}
recipes.add(recipe);
}, recipeType.get());
});
}
public CategoryBuilder<T> removeRecipes(Supplier<RecipeType<? extends T>> recipeType) {
return addRecipeListConsumer(recipes -> {
List<Recipe<?>> excludedRecipes = getTypedRecipes(recipeType.get());
recipes.removeIf(recipe -> {
for (Recipe<?> excludedRecipe : excludedRecipes) {
if (doInputsMatch(recipe, excludedRecipe)) {
return true;
}
}
return false;
});
});
}
public CategoryBuilder<T> catalystStack(Supplier<ItemStack> supplier) {
catalysts.add(supplier);
return this;
}
public CategoryBuilder<T> catalyst(Supplier<ItemLike> supplier) {
return catalystStack(() -> new ItemStack(supplier.get()
.asItem()));
}
public CategoryBuilder<T> icon(IDrawable icon) {
this.icon = icon;
return this;
}
public CategoryBuilder<T> itemIcon(ItemLike item) {
icon(new ItemIcon(() -> new ItemStack(item)));
return this;
}
public CategoryBuilder<T> doubleItemIcon(ItemLike item1, ItemLike item2) {
icon(new DoubleItemIcon(() -> new ItemStack(item1), () -> new ItemStack(item2)));
return this;
}
public CategoryBuilder<T> background(IDrawable background) {
this.background = background;
return this;
}
public CategoryBuilder<T> emptyBackground(int width, int height) {
background(new EmptyBackground(width, height));
return this;
}
public CreateRecipeCategory<T> build(String name, CreateRecipeCategory.Factory<T> factory) {
Supplier<List<T>> recipesSupplier;
if (predicate.test(AllConfigs.SERVER.recipes)) {
recipesSupplier = () -> {
List<T> recipes = new ArrayList<>();
for (Consumer<List<T>> consumer : recipeListConsumers)
consumer.accept(recipes);
return recipes;
};
} else {
recipesSupplier = () -> Collections.emptyList();
}
CreateRecipeCategory.Info<T> info = new CreateRecipeCategory.Info<>(
new mezz.jei.api.recipe.RecipeType<>(Create.asResource(name), recipeClass),
CreateLang.translateDirect("recipe." + name), background, icon, recipesSupplier, catalysts);
CreateRecipeCategory<T> category = factory.create(info);
allCategories.add(category);
return category;
}
}
public static void consumeAllRecipes(Consumer<Recipe<?>> consumer) {
Minecraft.getInstance()
.getConnection()
.getRecipeManager()
.getRecipes()
.forEach(consumer);
}
public static <T extends Recipe<?>> void consumeTypedRecipes(Consumer<T> consumer, RecipeType<?> type) {
Map<ResourceLocation, Recipe<?>> map = Minecraft.getInstance()
.getConnection()
.getRecipeManager().recipes.get(type);
if (map != null) {
map.values().forEach(recipe -> consumer.accept((T) recipe));
}
}
public static List<Recipe<?>> getTypedRecipes(RecipeType<?> type) {
List<Recipe<?>> recipes = new ArrayList<>();
consumeTypedRecipes(recipes::add, type);
return recipes;
}
public static List<Recipe<?>> getTypedRecipesExcluding(RecipeType<?> type, Predicate<Recipe<?>> exclusionPred) {
List<Recipe<?>> recipes = getTypedRecipes(type);
recipes.removeIf(exclusionPred);
return recipes;
}
public static boolean doInputsMatch(Recipe<?> recipe1, Recipe<?> recipe2) {
if (recipe1.getIngredients()
.isEmpty()
|| recipe2.getIngredients()
.isEmpty()) {
return false;
}
ItemStack[] matchingStacks = recipe1.getIngredients()
.get(0)
.getItems();
if (matchingStacks.length == 0) {
return false;
}
return recipe2.getIngredients()
.get(0)
.test(matchingStacks[0]);
}
}