Repository navigation
Expand file tree
/
Copy pathPotionHelperCommonCapabilities.java
More file actions
103 lines (93 loc) · 4.8 KB
/
Copy pathPotionHelperCommonCapabilities.java
File metadata and controls
103 lines (93 loc) · 4.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package net.minecraft.potion;
import com.google.common.collect.Lists;
import net.minecraft.core.Holder;
import net.minecraft.core.component.DataComponents;
import net.minecraft.core.component.predicates.PotionsPredicate;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.alchemy.Potion;
import net.minecraft.world.item.alchemy.PotionContents;
import net.minecraft.world.item.crafting.BrewingInput;
import net.minecraft.world.item.crafting.BrewingRecipe;
import net.minecraft.world.item.crafting.PotionIngredient;
import net.minecraft.world.item.crafting.RecipeHolder;
import net.minecraft.world.item.crafting.RecipeManager;
import net.minecraft.world.level.Level;
import net.neoforged.neoforge.server.ServerLifecycleHooks;
import org.cyclops.commoncapabilities.api.capability.itemhandler.ItemMatch;
import org.cyclops.commoncapabilities.api.capability.recipehandler.IRecipeDefinition;
import org.cyclops.commoncapabilities.api.capability.recipehandler.RecipeDefinition;
import org.cyclops.commoncapabilities.api.ingredient.IPrototypedIngredient;
import org.cyclops.commoncapabilities.api.ingredient.IngredientComponent;
import org.cyclops.commoncapabilities.api.ingredient.MixedIngredients;
import org.cyclops.commoncapabilities.api.ingredient.PrototypedIngredient;
import java.util.List;
import java.util.Optional;
/**
* Brewing became datapack-driven in Minecraft 26.3, so the recipes are read straight from
* {@link BrewingRecipe} instead of being derived by walking {@code PotionBrewing}'s mixes.
* @author rubensworks
*/
public class PotionHelperCommonCapabilities {
private static List<IRecipeDefinition> VANILLA_RECIPES = null;
public static List<IRecipeDefinition> getVanillaRecipes() {
if (VANILLA_RECIPES == null) {
VANILLA_RECIPES = Lists.newArrayList();
Level level = ServerLifecycleHooks.getCurrentServer().overworld();
if (level.recipeAccess() instanceof RecipeManager recipeManager) {
for (RecipeHolder<?> holder : recipeManager.getRecipes()) {
if (holder.value() instanceof BrewingRecipe recipe) {
addRecipes(recipe);
}
}
}
}
return VANILLA_RECIPES;
}
protected static void addRecipes(BrewingRecipe recipe) {
for (ItemStack reagent : getMatchingStacks(recipe.getReagent())) {
for (ItemStack input : getMatchingStacks(recipe.getInput())) {
// Let the recipe assemble the output itself, so subtypes that derive the output
// from the input container (as the vanilla mixes do) are handled correctly
ItemStack output = recipe.assemble(new BrewingInput(input, reagent));
if (!output.isEmpty()) {
addRecipe(
new PrototypedIngredient<>(IngredientComponent.ITEMSTACK, reagent, ItemMatch.ITEM | ItemMatch.DATA),
new PrototypedIngredient<>(IngredientComponent.ITEMSTACK, input, ItemMatch.ITEM | ItemMatch.DATA),
output);
}
}
}
}
/**
* Expand a potion ingredient into the concrete stacks it accepts:
* its container items, each carrying one of the potions its predicate allows.
*/
protected static List<ItemStack> getMatchingStacks(PotionIngredient ingredient) {
List<ItemStack> containers = ingredient.ingredient().items()
.map(ItemStack::new)
.toList();
Optional<PotionsPredicate> potionsPredicate = ingredient.potions();
if (potionsPredicate.isEmpty() || potionsPredicate.get().potions().isEmpty()) {
return containers;
}
List<ItemStack> stacks = Lists.newArrayList();
for (ItemStack container : containers) {
for (Holder<Potion> potion : potionsPredicate.get().potions().get()) {
ItemStack stack = container.copy();
stack.set(DataComponents.POTION_CONTENTS, new PotionContents(potion));
stacks.add(stack);
}
}
return stacks;
}
protected static void addRecipe(IPrototypedIngredient<ItemStack, Integer> reagent,
IPrototypedIngredient<ItemStack, Integer> input,
ItemStack output) {
IRecipeDefinition recipe = RecipeDefinition.ofIngredients(IngredientComponent.ITEMSTACK,
Lists.newArrayList(Lists.newArrayList(reagent), Lists.newArrayList(input), Lists.newArrayList(input), Lists.newArrayList(input)),
MixedIngredients.ofInstances(IngredientComponent.ITEMSTACK, Lists.newArrayList(ItemStack.EMPTY, output, output, output)));
if (!VANILLA_RECIPES.contains(recipe)) {
VANILLA_RECIPES.add(recipe);
}
}
}