Skip to content

Commit 68f5d8f

Browse files
committed
Support persisting the remainder item for the nutritional liquifier (mekanism/Mekanism-Feature-Requests#479)
1 parent 2b9d374 commit 68f5d8f

21 files changed

+386
-48
lines changed

build.gradle

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -391,8 +391,7 @@ dependencies {
391391

392392
def crt = "com.blamejared.crafttweaker:CraftTweaker-neoforge-${minecraft_version}:${crafttweaker_version}"
393393
compileOnly(crt)
394-
//TODO: Re-enable when it updates to neo changes
395-
//localRuntime(crt)
394+
localRuntime(crt)
396395
def jeiTweaker = "com.blamejared.jeitweaker:JeiTweaker-forge-1.20.1:${jeitweaker_version}"
397396
compileOnly(jeiTweaker)
398397
//TODO: Re-enable when it updates

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ yamlops_version=1.2.0
3737

3838
#Mod dependencies
3939
cc_tweaked_version=1.111.0
40-
crafttweaker_version=20.0.12
40+
crafttweaker_version=20.0.13
4141
ctm_version=1.2.0+1
4242
curios_version=9.0.2+1.21
4343
emi_version=1.1.7
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package mekanism.api.recipes;
2+
3+
import java.util.List;
4+
import java.util.Objects;
5+
import java.util.function.Predicate;
6+
import mekanism.api.annotations.NothingNullByDefault;
7+
import mekanism.api.recipes.ingredients.ItemStackIngredient;
8+
import net.minecraft.world.item.ItemStack;
9+
import net.minecraft.world.item.crafting.SingleRecipeInput;
10+
import net.minecraft.world.level.Level;
11+
import net.neoforged.neoforge.fluids.FluidStack;
12+
import org.jetbrains.annotations.Contract;
13+
import org.jetbrains.annotations.NotNull;
14+
15+
/**
16+
* Base class for defining ItemStack to fluid recipes with an optional item output.
17+
* <br>
18+
* Input: ItemStack
19+
* <br>
20+
* Output: FluidStack, Optional ItemStack
21+
*
22+
* @apiNote There is currently only one type of ItemStack to FluidStack recipe type:
23+
* <ul>
24+
* <li>Nutritional Liquification: These cannot currently be created, but are processed in the Nutritional Liquifier.</li>
25+
* </ul>
26+
*
27+
* @since 10.6.3
28+
*/
29+
@NothingNullByDefault
30+
public abstract class ItemStackToFluidOptionalItemRecipe extends MekanismRecipe<SingleRecipeInput> implements Predicate<@NotNull ItemStack> {
31+
32+
@Override
33+
public abstract boolean test(ItemStack itemStack);
34+
35+
@Override
36+
public boolean matches(SingleRecipeInput input, Level level) {
37+
//Don't match incomplete recipes or ones that don't match
38+
return !isIncomplete() && test(input.item());
39+
}
40+
41+
/**
42+
* Gets the input ingredient.
43+
*/
44+
public abstract ItemStackIngredient getInput();
45+
46+
/**
47+
* Gets a new output based on the given input.
48+
*
49+
* @param input Specific input.
50+
*
51+
* @return New output.
52+
*
53+
* @apiNote While Mekanism does not currently make use of the input, it is important to support it and pass the proper value in case any addons define input based
54+
* outputs where things like NBT may be different
55+
* @implNote The passed in input should <strong>NOT</strong> be modified.
56+
*/
57+
@Contract(value = "_ -> new", pure = true)
58+
public abstract FluidOptionalItemOutput getOutput(ItemStack input);
59+
60+
/**
61+
* For JEI, gets the output representations to display.
62+
*
63+
* @return Representation of the output, <strong>MUST NOT</strong> be modified.
64+
*/
65+
public abstract List<FluidOptionalItemOutput> getOutputDefinition();
66+
67+
@Override
68+
public boolean isIncomplete() {
69+
return getInput().hasNoMatchingInstances();
70+
}
71+
72+
/**
73+
* @apiNote Fluid must be present, but the item may be empty.
74+
*/
75+
public record FluidOptionalItemOutput(FluidStack fluid, ItemStack optionalItem) {
76+
77+
public FluidOptionalItemOutput {
78+
Objects.requireNonNull(fluid, "Fluid output cannot be null.");
79+
Objects.requireNonNull(optionalItem, "Item output cannot be null.");
80+
if (fluid.isEmpty()) {
81+
throw new IllegalArgumentException("Fluid output cannot be empty.");
82+
}
83+
}
84+
85+
/**
86+
* Copies the backing objects of this output object.
87+
*/
88+
public FluidOptionalItemOutput copy() {
89+
return new FluidOptionalItemOutput(fluid.copy(), optionalItem.copy());
90+
}
91+
}
92+
}

src/api/java/mekanism/api/recipes/ItemStackToFluidRecipe.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,7 @@
1818
* <br>
1919
* Output: FluidStack
2020
*
21-
* @apiNote There is currently only one type of ItemStack to FluidStack recipe type:
22-
* <ul>
23-
* <li>Nutritional Liquification: These cannot currently be created, but are processed in the Nutritional Liquifier.</li>
24-
* </ul>
21+
* @apiNote There is currently no types of ItemStack to FluidStack recipe type
2522
*/
2623
@NothingNullByDefault
2724
public abstract class ItemStackToFluidRecipe extends MekanismRecipe<SingleRecipeInput> implements Predicate<@NotNull ItemStack> {
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package mekanism.api.recipes.basic;
2+
3+
import java.util.Collections;
4+
import java.util.List;
5+
import java.util.Objects;
6+
import mekanism.api.annotations.NothingNullByDefault;
7+
import mekanism.api.recipes.ItemStackToFluidOptionalItemRecipe;
8+
import mekanism.api.recipes.ingredients.ItemStackIngredient;
9+
import net.minecraft.world.item.ItemStack;
10+
import org.jetbrains.annotations.Contract;
11+
12+
/**
13+
* Basic implementation of {@link ItemStackToFluidOptionalItemRecipe}
14+
* @since 10.6.3
15+
*/
16+
@NothingNullByDefault
17+
public abstract class BasicItemStackToFluidOptionalItemRecipe extends ItemStackToFluidOptionalItemRecipe {
18+
19+
protected final ItemStackIngredient input;
20+
protected final FluidOptionalItemOutput output;
21+
22+
/**
23+
* @param input Input.
24+
* @param output Output.
25+
*/
26+
public BasicItemStackToFluidOptionalItemRecipe(ItemStackIngredient input, FluidOptionalItemOutput output) {
27+
this.input = Objects.requireNonNull(input, "Input cannot be null.");
28+
Objects.requireNonNull(output, "Output cannot be null.");
29+
this.output = output.copy();
30+
}
31+
32+
@Override
33+
public boolean test(ItemStack itemStack) {
34+
return input.test(itemStack);
35+
}
36+
37+
@Override
38+
public ItemStackIngredient getInput() {
39+
return input;
40+
}
41+
42+
@Override
43+
@Contract(value = "_ -> new", pure = true)
44+
public FluidOptionalItemOutput getOutput(ItemStack input) {
45+
return output.copy();
46+
}
47+
48+
@Override
49+
public List<FluidOptionalItemOutput> getOutputDefinition() {
50+
return Collections.singletonList(output);
51+
}
52+
}

src/api/java/mekanism/api/recipes/cache/OneInputCachedRecipe.java

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
import mekanism.api.recipes.ElectrolysisRecipe;
1414
import mekanism.api.recipes.ElectrolysisRecipe.ElectrolysisRecipeOutput;
1515
import mekanism.api.recipes.FluidToFluidRecipe;
16+
import mekanism.api.recipes.ItemStackToFluidOptionalItemRecipe;
17+
import mekanism.api.recipes.ItemStackToFluidOptionalItemRecipe.FluidOptionalItemOutput;
1618
import mekanism.api.recipes.ItemStackToFluidRecipe;
1719
import mekanism.api.recipes.ItemStackToItemStackRecipe;
1820
import mekanism.api.recipes.MekanismRecipe;
@@ -35,6 +37,9 @@
3537
@NothingNullByDefault
3638
public class OneInputCachedRecipe<INPUT, OUTPUT, RECIPE extends MekanismRecipe<?> & Predicate<INPUT>> extends CachedRecipe<RECIPE> {
3739

40+
private static final Predicate<ElectrolysisRecipeOutput> SEPARATOR_OUTPUT_EMPTY = output -> output.left().isEmpty() || output.right().isEmpty();
41+
private static final Predicate<FluidOptionalItemOutput> FLUID_OPTIONAL_ITEM_OUTPUT_EMPTY = output -> output.fluid().isEmpty();
42+
3843
private final IInputHandler<INPUT> inputHandler;
3944
private final IOutputHandler<OUTPUT> outputHandler;
4045
private final Predicate<INPUT> inputEmptyCheck;
@@ -108,7 +113,7 @@ protected void finishProcessing(int operations) {
108113
public static OneInputCachedRecipe<@NotNull FluidStack, @NotNull ElectrolysisRecipeOutput, ElectrolysisRecipe> separating(ElectrolysisRecipe recipe,
109114
BooleanSupplier recheckAllErrors, IInputHandler<@NotNull FluidStack> inputHandler, IOutputHandler<@NotNull ElectrolysisRecipeOutput> outputHandler) {
110115
return new OneInputCachedRecipe<>(recipe, recheckAllErrors, inputHandler, outputHandler, recipe::getInput, recipe::getOutput, ConstantPredicates.FLUID_EMPTY,
111-
ConstantPredicates.alwaysFalse());
116+
SEPARATOR_OUTPUT_EMPTY);
112117
}
113118

114119
/**
@@ -156,6 +161,24 @@ protected void finishProcessing(int operations) {
156161
ConstantPredicates.FLUID_EMPTY);
157162
}
158163

164+
/**
165+
* Base implementation for handling ItemStack to Fluid with optional Item Recipes.
166+
*
167+
* @param recipe Recipe.
168+
* @param recheckAllErrors Returns {@code true} if processing should be continued even if an error is hit in order to gather all the errors. It is recommended to not
169+
* do this every tick or if there is no one viewing recipes.
170+
* @param inputHandler Input handler.
171+
* @param outputHandler Output handler.
172+
*
173+
* @since 10.6.3
174+
*/
175+
public static OneInputCachedRecipe<@NotNull ItemStack, @NotNull FluidOptionalItemOutput, ItemStackToFluidOptionalItemRecipe> itemToFluidOptionalItem(
176+
ItemStackToFluidOptionalItemRecipe recipe, BooleanSupplier recheckAllErrors, IInputHandler<@NotNull ItemStack> inputHandler,
177+
IOutputHandler<@NotNull FluidOptionalItemOutput> outputHandler) {
178+
return new OneInputCachedRecipe<>(recipe, recheckAllErrors, inputHandler, outputHandler, recipe::getInput, recipe::getOutput, ConstantPredicates.ITEM_EMPTY,
179+
FLUID_OPTIONAL_ITEM_OUTPUT_EMPTY);
180+
}
181+
159182
/**
160183
* Base implementation for handling ItemStack to Chemical Recipes.
161184
*

src/api/java/mekanism/api/recipes/outputs/OutputHelper.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import mekanism.api.inventory.IInventorySlot;
1212
import mekanism.api.math.MathUtils;
1313
import mekanism.api.recipes.ElectrolysisRecipe.ElectrolysisRecipeOutput;
14+
import mekanism.api.recipes.ItemStackToFluidOptionalItemRecipe.FluidOptionalItemOutput;
1415
import mekanism.api.recipes.PressurizedReactionRecipe.PressurizedReactionRecipeOutput;
1516
import mekanism.api.recipes.SawmillRecipe.ChanceOutput;
1617
import mekanism.api.recipes.cache.CachedRecipe.OperationTracker;
@@ -165,6 +166,40 @@ public void calculateOperationsCanSupport(OperationTracker tracker, PressurizedR
165166
};
166167
}
167168

169+
/**
170+
* Wraps a fluid tank and an inventory slot an {@link IOutputHandler}.
171+
*
172+
* @param tank Tank to wrap.
173+
* @param slot Slot to wrap.
174+
* @param tankNotEnoughSpaceError The error to apply if the tank output causes the recipe to not be able to perform any operations.
175+
* @param slotNotEnoughSpaceError The error to apply if the slot output causes the recipe to not be able to perform any operations.
176+
*
177+
* @since 10.6.3
178+
*/
179+
public static IOutputHandler<@NotNull FluidOptionalItemOutput> getOutputHandler(IExtendedFluidTank tank, RecipeError tankNotEnoughSpaceError,
180+
IInventorySlot slot, RecipeError slotNotEnoughSpaceError) {
181+
Objects.requireNonNull(tank, "Tank cannot be null.");
182+
Objects.requireNonNull(slot, "Slot cannot be null.");
183+
Objects.requireNonNull(tankNotEnoughSpaceError, "Tank not enough space error cannot be null.");
184+
Objects.requireNonNull(slotNotEnoughSpaceError, "Slot not enough space error cannot be null.");
185+
return new IOutputHandler<>() {
186+
187+
@Override
188+
public void handleOutput(FluidOptionalItemOutput toOutput, int operations) {
189+
OutputHelper.handleOutput(tank, toOutput.fluid(), operations);
190+
OutputHelper.handleOutput(slot, toOutput.optionalItem(), operations);
191+
}
192+
193+
@Override
194+
public void calculateOperationsCanSupport(OperationTracker tracker, FluidOptionalItemOutput toOutput) {
195+
OutputHelper.calculateOperationsCanSupport(tracker, tankNotEnoughSpaceError, tank, toOutput.fluid());
196+
if (tracker.shouldContinueChecking()) {
197+
OutputHelper.calculateOperationsCanSupport(tracker, slotNotEnoughSpaceError, slot, toOutput.optionalItem());
198+
}
199+
}
200+
};
201+
}
202+
168203
/**
169204
* Wraps two gas tank into an {@link IOutputHandler}.
170205
*

src/datagen/generated/mekanism/.cache/2ca94f3a6e22cb9eec299788405fc6e4ad158c09

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/datagen/generated/mekanism/data/mekanism/computer_help/jekyll.md

Lines changed: 6 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/datagen/generated/mekanism/data/mekanism/computer_help/methods.csv

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)