-
Notifications
You must be signed in to change notification settings - Fork 301
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix #2968 Add Fabric support for Potion recipes
- Loading branch information
Showing
14 changed files
with
306 additions
and
193 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
138 changes: 138 additions & 0 deletions
138
Common/src/main/java/mezz/jei/common/util/BrewingRecipeMakerCommon.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
package mezz.jei.common.util; | ||
|
||
import mezz.jei.api.constants.VanillaTypes; | ||
import mezz.jei.api.ingredients.IIngredientHelper; | ||
import mezz.jei.api.ingredients.subtypes.UidContext; | ||
import mezz.jei.api.recipe.vanilla.IJeiBrewingRecipe; | ||
import mezz.jei.api.recipe.vanilla.IVanillaRecipeFactory; | ||
import mezz.jei.api.runtime.IIngredientManager; | ||
import mezz.jei.common.ingredients.IngredientSet; | ||
import mezz.jei.common.platform.IPlatformIngredientHelper; | ||
import mezz.jei.common.platform.IPlatformRegistry; | ||
import mezz.jei.common.platform.Services; | ||
import net.minecraft.core.Registry; | ||
import net.minecraft.resources.ResourceLocation; | ||
import net.minecraft.world.item.ItemStack; | ||
import net.minecraft.world.item.alchemy.Potion; | ||
import net.minecraft.world.item.alchemy.PotionBrewing; | ||
import net.minecraft.world.item.alchemy.PotionUtils; | ||
import net.minecraft.world.item.alchemy.Potions; | ||
import org.apache.logging.log4j.LogManager; | ||
import org.apache.logging.log4j.Logger; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Arrays; | ||
import java.util.Collection; | ||
import java.util.HashSet; | ||
import java.util.List; | ||
import java.util.Objects; | ||
import java.util.Set; | ||
|
||
public class BrewingRecipeMakerCommon { | ||
private static final Logger LOGGER = LogManager.getLogger(); | ||
|
||
public static Set<IJeiBrewingRecipe> getVanillaBrewingRecipes( | ||
IVanillaRecipeFactory recipeFactory, | ||
IIngredientManager ingredientManager, | ||
IVanillaPotionOutputSupplier vanillaOutputSupplier | ||
) { | ||
Set<IJeiBrewingRecipe> recipes = new HashSet<>(); | ||
IPlatformRegistry<Potion> potionRegistry = Services.PLATFORM.getRegistry(Registry.POTION_REGISTRY); | ||
IngredientSet<ItemStack> knownPotions = getBaseKnownPotions(ingredientManager, potionRegistry); | ||
|
||
List<ItemStack> potionReagents = ingredientManager.getAllItemStacks().stream() | ||
.filter(BrewingRecipeMakerCommon::isIngredient) | ||
.toList(); | ||
|
||
boolean foundNewPotions; | ||
do { | ||
List<ItemStack> newPotions = getNewPotions( | ||
recipeFactory, | ||
potionRegistry, | ||
knownPotions, | ||
potionReagents, | ||
vanillaOutputSupplier, | ||
recipes | ||
); | ||
foundNewPotions = !newPotions.isEmpty(); | ||
knownPotions.addAll(newPotions); | ||
} while (foundNewPotions); | ||
|
||
return recipes; | ||
} | ||
|
||
private static boolean isIngredient(ItemStack itemStack) { | ||
try { | ||
return PotionBrewing.isIngredient(itemStack); | ||
} catch (RuntimeException | LinkageError e) { | ||
String itemStackInfo = ErrorUtil.getItemStackInfo(itemStack); | ||
LOGGER.error("Failed to check if item is a potion reagent {}.", itemStackInfo, e); | ||
return false; | ||
} | ||
} | ||
|
||
private static IngredientSet<ItemStack> getBaseKnownPotions(IIngredientManager ingredientManager, IPlatformRegistry<Potion> potionRegistry) { | ||
IPlatformIngredientHelper ingredientHelper = Services.PLATFORM.getIngredientHelper(); | ||
List<ItemStack> potionContainers = ingredientHelper.getPotionContainers().stream() | ||
.flatMap(potionItem -> Arrays.stream(potionItem.getItems())) | ||
.toList(); | ||
|
||
IIngredientHelper<ItemStack> itemStackHelper = ingredientManager.getIngredientHelper(VanillaTypes.ITEM_STACK); | ||
IngredientSet<ItemStack> knownPotions = IngredientSet.create(itemStackHelper, UidContext.Ingredient); | ||
|
||
potionRegistry.getValues() | ||
.filter(potion -> potion != Potions.EMPTY) // skip the "un-craft-able" vanilla potions | ||
.forEach(potion -> { | ||
for (ItemStack potionContainer : potionContainers) { | ||
ItemStack result = PotionUtils.setPotion(potionContainer.copy(), potion); | ||
knownPotions.add(result); | ||
} | ||
}); | ||
return knownPotions; | ||
} | ||
|
||
private static List<ItemStack> getNewPotions( | ||
IVanillaRecipeFactory recipeFactory, | ||
IPlatformRegistry<Potion> potionRegistry, | ||
Collection<ItemStack> knownPotions, | ||
List<ItemStack> potionReagents, | ||
IVanillaPotionOutputSupplier vanillaOutputSupplier, | ||
Collection<IJeiBrewingRecipe> recipes | ||
) { | ||
List<ItemStack> newPotions = new ArrayList<>(); | ||
for (ItemStack potionInput : knownPotions) { | ||
for (ItemStack potionReagent : potionReagents) { | ||
ItemStack potionOutput = vanillaOutputSupplier.getOutput(potionInput.copy(), potionReagent); | ||
if (potionOutput.isEmpty()) { | ||
continue; | ||
} | ||
|
||
if (potionInput.getItem() == potionOutput.getItem()) { | ||
Potion potionOutputType = PotionUtils.getPotion(potionOutput); | ||
if (potionOutputType == Potions.WATER) { | ||
continue; | ||
} | ||
|
||
Potion potionInputType = PotionUtils.getPotion(potionInput); | ||
ResourceLocation inputId = potionRegistry.getRegistryName(potionInputType); | ||
ResourceLocation outputId = potionRegistry.getRegistryName(potionOutputType); | ||
if (Objects.equals(inputId, outputId)) { | ||
continue; | ||
} | ||
} | ||
|
||
IJeiBrewingRecipe recipe = recipeFactory.createBrewingRecipe(List.of(potionReagent), potionInput.copy(), potionOutput); | ||
if (!recipes.contains(recipe)) { | ||
recipes.add(recipe); | ||
newPotions.add(potionOutput); | ||
} | ||
} | ||
} | ||
return newPotions; | ||
} | ||
|
||
@FunctionalInterface | ||
public interface IVanillaPotionOutputSupplier { | ||
ItemStack getOutput(ItemStack input, ItemStack ingredient); | ||
} | ||
} |
36 changes: 36 additions & 0 deletions
36
Fabric/src/main/java/mezz/jei/fabric/platform/BrewingRecipeMaker.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package mezz.jei.fabric.platform; | ||
|
||
import mezz.jei.api.recipe.vanilla.IJeiBrewingRecipe; | ||
import mezz.jei.api.recipe.vanilla.IVanillaRecipeFactory; | ||
import mezz.jei.api.runtime.IIngredientManager; | ||
import mezz.jei.common.util.BrewingRecipeMakerCommon; | ||
import net.minecraft.world.item.ItemStack; | ||
import net.minecraft.world.item.alchemy.PotionBrewing; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Comparator; | ||
import java.util.List; | ||
import java.util.Set; | ||
|
||
public class BrewingRecipeMaker { | ||
public static List<IJeiBrewingRecipe> getBrewingRecipes(IIngredientManager ingredientManager, IVanillaRecipeFactory vanillaRecipeFactory) { | ||
Set<IJeiBrewingRecipe> recipes = BrewingRecipeMakerCommon.getVanillaBrewingRecipes( | ||
vanillaRecipeFactory, | ||
ingredientManager, | ||
BrewingRecipeMaker::getOutput | ||
); | ||
|
||
List<IJeiBrewingRecipe> recipeList = new ArrayList<>(recipes); | ||
recipeList.sort(Comparator.comparingInt(IJeiBrewingRecipe::getBrewingSteps)); | ||
|
||
return recipeList; | ||
} | ||
|
||
private static ItemStack getOutput(ItemStack input, ItemStack ingredient) { | ||
ItemStack result = PotionBrewing.mix(ingredient, input); | ||
if (result != input) { | ||
return result; | ||
} | ||
return ItemStack.EMPTY; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
75 changes: 75 additions & 0 deletions
75
Forge/src/main/java/mezz/jei/forge/platform/BrewingRecipeMaker.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
package mezz.jei.forge.platform; | ||
|
||
import mezz.jei.api.recipe.vanilla.IJeiBrewingRecipe; | ||
import mezz.jei.api.recipe.vanilla.IVanillaRecipeFactory; | ||
import mezz.jei.api.runtime.IIngredientManager; | ||
import mezz.jei.common.util.BrewingRecipeMakerCommon; | ||
import net.minecraft.world.item.ItemStack; | ||
import net.minecraft.world.item.crafting.Ingredient; | ||
import net.minecraftforge.common.brewing.BrewingRecipe; | ||
import net.minecraftforge.common.brewing.BrewingRecipeRegistry; | ||
import net.minecraftforge.common.brewing.IBrewingRecipe; | ||
import net.minecraftforge.common.brewing.VanillaBrewingRecipe; | ||
import org.apache.logging.log4j.LogManager; | ||
import org.apache.logging.log4j.Logger; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Collection; | ||
import java.util.HashSet; | ||
import java.util.List; | ||
import java.util.Set; | ||
|
||
public class BrewingRecipeMaker { | ||
private static final Logger LOGGER = LogManager.getLogger(); | ||
|
||
public static List<IJeiBrewingRecipe> getBrewingRecipes(IIngredientManager ingredientManager, IVanillaRecipeFactory vanillaRecipeFactory) { | ||
Collection<IBrewingRecipe> brewingRecipes = BrewingRecipeRegistry.getRecipes(); | ||
|
||
Set<IJeiBrewingRecipe> recipes = brewingRecipes.stream() | ||
.filter(VanillaBrewingRecipe.class::isInstance) | ||
.map(VanillaBrewingRecipe.class::cast) | ||
.findFirst() | ||
.map(vanillaBrewingRecipe -> | ||
BrewingRecipeMakerCommon.getVanillaBrewingRecipes( | ||
vanillaRecipeFactory, | ||
ingredientManager, | ||
vanillaBrewingRecipe::getOutput | ||
) | ||
) | ||
.orElseGet(HashSet::new); | ||
|
||
addModdedBrewingRecipes( | ||
vanillaRecipeFactory, | ||
brewingRecipes, | ||
recipes | ||
); | ||
|
||
return new ArrayList<>(recipes); | ||
} | ||
|
||
private static void addModdedBrewingRecipes( | ||
IVanillaRecipeFactory vanillaRecipeFactory, | ||
Collection<IBrewingRecipe> brewingRecipes, | ||
Collection<IJeiBrewingRecipe> recipes | ||
) { | ||
Set<Class<?>> unhandledRecipeClasses = new HashSet<>(); | ||
for (IBrewingRecipe iBrewingRecipe : brewingRecipes) { | ||
if (iBrewingRecipe instanceof BrewingRecipe brewingRecipe) { | ||
ItemStack[] ingredients = brewingRecipe.getIngredient().getItems(); | ||
if (ingredients.length > 0) { | ||
Ingredient inputIngredient = brewingRecipe.getInput(); | ||
ItemStack output = brewingRecipe.getOutput(); | ||
ItemStack[] inputs = inputIngredient.getItems(); | ||
IJeiBrewingRecipe recipe = vanillaRecipeFactory.createBrewingRecipe(List.of(ingredients), List.of(inputs), output); | ||
recipes.add(recipe); | ||
} | ||
} else if (!(iBrewingRecipe instanceof VanillaBrewingRecipe)) { | ||
Class<?> recipeClass = iBrewingRecipe.getClass(); | ||
if (!unhandledRecipeClasses.contains(recipeClass)) { | ||
unhandledRecipeClasses.add(recipeClass); | ||
LOGGER.debug("Can't handle brewing recipe class: {}", recipeClass); | ||
} | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.