Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/ADDING_RECIPES.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ ServerEvents.recipes(event => {
// add all the inputs and outputs:
.itemIn("64x #minecraft:logs_that_burn")
.itemOut("64x minecraft:charcoal")
.fluidIn("modern_industrialization:oxygen", 1000)
.fluidOut("modern_industrialization:creosote", 5000)
.fluidIn("1000x modern_industrialization:oxygen")
.fluidOut("5000x modern_industrialization:creosote")
})
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.item.crafting.RecipeManager;
import net.minecraft.world.level.ItemLike;
import net.neoforged.neoforge.fluids.crafting.FluidIngredient;
import org.jetbrains.annotations.Nullable;

/**
Expand Down Expand Up @@ -111,6 +112,8 @@ public interface SlotBuilder {

SlotBuilder fluid(FluidVariant fluid, long amount, float probability);

SlotBuilder fluid(FluidIngredient ingredient, long amount, float probability);

default SlotBuilder item(ItemStack stack) {
return item(stack, 1);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,15 @@
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.stream.Stream;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.Ingredient;
import net.neoforged.neoforge.fluids.crafting.FluidIngredient;
import org.jetbrains.annotations.Nullable;

class ViewerCategoryEmi<D> extends EmiRecipeCategory {
Expand Down Expand Up @@ -165,6 +167,19 @@ public ViewerCategory.SlotBuilder fluid(FluidVariant fluid, long amount, float p
return this;
}

@Override
public ViewerCategory.SlotBuilder fluid(FluidIngredient ingredient, long amount, float probability) {
isFluid = true;
hasBackground = false;
ing = EmiIngredient.of(
Stream.of(ingredient.getStacks())
.map(fs -> EmiStack.of(fs.getFluid(), fs.getComponentsPatch()))
.toList(),
amount);
processProbability(probability);
return this;
}

private void processProbability(float probability) {
if (probability == 0) {
markCatalyst();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.Ingredient;
import net.neoforged.neoforge.fluids.FluidType;
import net.neoforged.neoforge.fluids.crafting.FluidIngredient;
import org.jetbrains.annotations.Nullable;

class ViewerCategoryJei<D> extends AbstractRecipeCategory<D> {
Expand Down Expand Up @@ -135,6 +136,18 @@ public ViewerCategory.SlotBuilder fluid(FluidVariant fluid, long amount, float p
return this;
}

@Override
public ViewerCategory.SlotBuilder fluid(FluidIngredient ingredient, long amount, float probability) {
for (var fs : ingredient.getStacks()) {
slotBuilder.addFluidStack(fs.getFluid(), amount, fs.getComponentsPatch());
}
// This call displays the full sprite (instead of JEI's partial rendering)
slotBuilder.setFluidRenderer(1, false, 16, 16);
addProbability(slotBuilder, probability);
slotBuilder.setBackground(fluidSlot, -1, -1);
return this;
}

private ViewerCategory.SlotBuilder items(List<ItemStack> stacks, float probability) {
slotBuilder.addItemStacks(stacks);
addProbability(slotBuilder, probability);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.Ingredient;
import net.neoforged.neoforge.fluids.crafting.FluidIngredient;
import org.jetbrains.annotations.Nullable;

class ViewerCategoryRei<D> implements DisplayCategory<ViewerCategoryRei<D>.ViewerDisplay> {
Expand Down Expand Up @@ -173,6 +174,16 @@ public ViewerCategory.SlotBuilder fluid(FluidVariant fluid, long amount, float p
return this;
}

@Override
public ViewerCategory.SlotBuilder fluid(FluidIngredient ingredient, long amount, float probability) {
isFluid = true;
hasBackground = false;
for (var fs : ingredient.getStacks()) {
ing.add(ReiSlotUtil.createFluidEntryStack(FluidVariant.of(fs), amount, probability, input));
}
return this;
}

private ViewerCategory.SlotBuilder items(List<ItemStack> stacks, float probability) {
for (var stack : stacks) {
ing.add(EntryStacks.of(stack).tooltip(ReiSlotUtil.getProbabilitySetting(probability, input)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ private void addFluidInputs(LayoutBuilder builder, MachineRecipe recipe) {

if (i < recipe.fluidInputs.size()) {
var input = recipe.fluidInputs.get(i);
slot.fluid(FluidVariant.of(input.fluid()), input.amount(), input.probability());
slot.fluid(input.fluid(), input.amount(), input.probability());
} else {
slot.variant(FluidVariant.blank());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

import aztech.modern_industrialization.MI;
import aztech.modern_industrialization.machines.recipe.MachineRecipe;
import dev.latvian.mods.kubejs.core.RegistryObjectKJS;
import dev.latvian.mods.kubejs.fluid.FluidWrapper;
import dev.latvian.mods.kubejs.recipe.KubeRecipe;
import dev.latvian.mods.kubejs.recipe.component.SimpleRecipeComponent;
Expand All @@ -33,8 +34,6 @@
import dev.latvian.mods.kubejs.recipe.match.ReplacementMatchInfo;
import dev.latvian.mods.kubejs.util.RegistryAccessContainer;
import dev.latvian.mods.rhino.Context;
import net.minecraft.world.level.material.Fluids;
import net.neoforged.neoforge.fluids.FluidStack;

public class FluidInputComponent extends SimpleRecipeComponent<MachineRecipe.FluidInput> {
public static final FluidInputComponent FLUID_INPUT = new FluidInputComponent();
Expand All @@ -45,35 +44,35 @@ public FluidInputComponent() {

@Override
public MachineRecipe.FluidInput wrap(Context cx, KubeRecipe recipe, Object from) {
var fs = FluidWrapper.wrap(RegistryAccessContainer.of(cx), from);
return new MachineRecipe.FluidInput(fs.getFluid(), fs.getAmount(), 1);
var fs = FluidWrapper.wrapSizedIngredient(RegistryAccessContainer.of(cx), from);
return new MachineRecipe.FluidInput(fs.ingredient(), fs.amount(), 1);
}

@Override
public boolean matches(Context cx, KubeRecipe recipe, MachineRecipe.FluidInput value, ReplacementMatchInfo match) {
return match.match() instanceof FluidMatch m && m.matches(cx, new FluidStack(value.fluid(), 1), match.exact());
return match.match() instanceof FluidMatch m && m.matches(cx, value.fluid(), match.exact());
}

@Override
public MachineRecipe.FluidInput replace(Context cx, KubeRecipe recipe, MachineRecipe.FluidInput original, ReplacementMatchInfo match,
Object with) {
if (matches(cx, recipe, original, match)) {
var fs = FluidWrapper.wrap(RegistryAccessContainer.of(cx), with);
return new MachineRecipe.FluidInput(fs.getFluid(), original.amount(), original.probability());
var fi = FluidWrapper.wrapIngredient(RegistryAccessContainer.of(cx), with);
return new MachineRecipe.FluidInput(fi, original.amount(), original.probability());
} else {
return original;
}
}

@Override
public boolean isEmpty(MachineRecipe.FluidInput value) {
return value.amount() <= 0 || value.fluid().isSame(Fluids.EMPTY);
return value.amount() <= 0 || value.fluid().isEmpty();
}

@Override
public void buildUniqueId(UniqueIdBuilder builder, MachineRecipe.FluidInput value) {
if (!isEmpty(value)) {
builder.append(value.fluid().builtInRegistryHolder().getKey().location());
builder.append(((RegistryObjectKJS) value.fluid().getStacks()[0].getFluid()).kjs$getIdLocation());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,23 @@
import aztech.modern_industrialization.machines.recipe.MachineRecipe;
import aztech.modern_industrialization.machines.recipe.condition.MachineProcessCondition;
import aztech.modern_industrialization.thirdparty.fabrictransfer.api.item.ItemVariant;
import com.mojang.logging.LogUtils;
import dev.latvian.mods.kubejs.recipe.KubeRecipe;
import dev.latvian.mods.kubejs.recipe.RecipeKey;
import dev.latvian.mods.kubejs.recipe.schema.KubeRecipeFactory;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.material.Fluid;
import net.neoforged.neoforge.common.crafting.SizedIngredient;
import net.neoforged.neoforge.fluids.FluidStack;
import net.neoforged.neoforge.fluids.crafting.FluidIngredient;
import net.neoforged.neoforge.fluids.crafting.SizedFluidIngredient;
import org.slf4j.Logger;

public class MachineKubeRecipe extends KubeRecipe implements ProcessConditionHelper {
private static final Logger LOGGER = LogUtils.getLogger();
public static final KubeRecipeFactory FACTORY = new KubeRecipeFactory(MI.id("machine"), MachineKubeRecipe.class, MachineKubeRecipe::new);

private <T> MachineKubeRecipe addToList(RecipeKey<List<T>> key, T element) {
Expand Down Expand Up @@ -64,19 +71,73 @@ public MachineKubeRecipe itemOut(ItemStack output, float chance) {
return addToList(MachineRecipeSchema.ITEM_OUTPUTS, new MachineRecipe.ItemOutput(ItemVariant.of(output), output.getCount(), chance));
}

public MachineKubeRecipe fluidIn(Fluid fluid, long mbs) {
return fluidIn(fluid, mbs, 1F);
public MachineKubeRecipe fluidIn(SizedFluidIngredient ingredient) {
return fluidInInternal(ingredient, 1F); // skip chance == 1 check
}

public MachineKubeRecipe fluidIn(Fluid fluid, long mbs, float probability) {
return addToList(MachineRecipeSchema.FLUID_INPUTS, new MachineRecipe.FluidInput(fluid, mbs, probability));
public MachineKubeRecipe fluidIn(SizedFluidIngredient ingredient, float chance) {
// TODO: remove this mess once we don't need to worry about backwards compat anymore.
if ((ingredient.amount() == 1 || ingredient.amount() == 1000) && chance > 1) {
LOGGER.warn("fluidIn with separate fluid and amount is deprecated. Use fluidIn(\"%dx %s\") notation instead.".formatted(
(int) chance,
BuiltInRegistries.FLUID.getKey(ingredient.ingredient().getStacks()[0].getFluid())));
return fluidIn(new SizedFluidIngredient(ingredient.ingredient(), (int) chance));
} else if (ingredient.amount() == 1000 && chance == 1) {
throw new IllegalArgumentException(
"fluidIn(\"some_fluid\", 1) is ambiguous. Use either fluidIn(\"1x some_fluid\") or fluidIn(\"some_fluid\") depending on what you meant.");
}

return fluidInInternal(ingredient, chance);
}

private MachineKubeRecipe fluidInInternal(SizedFluidIngredient ingredient, float chance) {
if (chance > 1) {
throw new IllegalArgumentException("Fluid input chance must be between 0 and 1. It is " + chance);
}
return addToList(MachineRecipeSchema.FLUID_INPUTS, new MachineRecipe.FluidInput(ingredient.ingredient(), ingredient.amount(), chance));
}

public MachineKubeRecipe fluidOut(FluidStack output) {
return fluidOutInternal(output, 1F); // skip chance == 1 check
}

public MachineKubeRecipe fluidOut(FluidStack output, float chance) {
// TODO: remove this mess once we don't need to worry about backwards compat anymore.
if ((output.getAmount() == 1 || output.getAmount() == 1000) && chance > 1) {
LOGGER.warn("fluidOut with separate fluid and amount is deprecated. Use fluidOut(\"%dx %s\") notation instead.".formatted(
(int) chance,
BuiltInRegistries.FLUID.getKey(output.getFluid())));
return fluidOut(output.copyWithAmount((int) chance));
} else if (output.getAmount() == 1000 && chance == 1) {
throw new IllegalArgumentException(
"fluidOut(\"some_fluid\", 1) is ambiguous. Use either fluidOut(\"1x some_fluid\") or fluidOut(\"some_fluid\") depending on what you meant.");
}

return fluidOutInternal(output, chance);
}

private MachineKubeRecipe fluidOutInternal(FluidStack output, float chance) {
if (!output.isComponentsPatchEmpty()) {
throw new IllegalArgumentException("FluidStack components are not supported in machine recipe outputs.");
}
return addToList(MachineRecipeSchema.FLUID_OUTPUTS, new MachineRecipe.FluidOutput(output.getFluid(), output.getAmount(), chance));
}

public MachineKubeRecipe fluidOut(Fluid fluid, long mbs) {
return fluidOut(fluid, mbs, 1F);
@Deprecated(forRemoval = true)
public MachineKubeRecipe fluidIn(FluidIngredient fluid, long mbs, float probability) {
LOGGER.warn("fluidIn with separate fluid and amount is deprecated. Use fluidIn(\"%dx %s\", %f) notation instead.".formatted(
mbs,
BuiltInRegistries.FLUID.getKey(fluid.getStacks()[0].getFluid()),
probability));
return fluidIn(new SizedFluidIngredient(fluid, (int) mbs), probability);
}

@Deprecated(forRemoval = true)
public MachineKubeRecipe fluidOut(Fluid fluid, long mbs, float probability) {
LOGGER.warn("fluidOut with separate fluid and amount is deprecated. Use fluidOut(\"%dx %s\", %f) notation instead.".formatted(
mbs,
BuiltInRegistries.FLUID.getKey(fluid),
probability));
return addToList(MachineRecipeSchema.FLUID_OUTPUTS, new MachineRecipe.FluidOutput(fluid, mbs, probability));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.RecipeHolder;
import net.minecraft.world.level.material.Fluid;
import net.neoforged.neoforge.fluids.FluidStack;
import net.neoforged.neoforge.fluids.FluidUtil;
import net.neoforged.neoforge.fluids.crafting.FluidIngredient;
import org.jetbrains.annotations.Nullable;

public class CrafterComponent implements IComponent.ServerOnly, CrafterAccess {
Expand Down Expand Up @@ -474,7 +477,7 @@ protected boolean takeFluidInputs(MachineRecipe recipe, boolean simulate) {
}
long remainingAmount = input.amount();
for (ConfigurableFluidStack stack : stacks) {
if (stack.getResource().equals(FluidVariant.of(input.fluid()))) {
if (fluidIngredientMatch(stack.getResource(), input.fluid())) {
long taken = Math.min(remainingAmount, stack.getAmount());
if (taken > 0 && !simulate) {
behavior.getStatsOrDummy().addUsedFluids(stack.getResource().getFluid(), taken);
Expand All @@ -491,6 +494,17 @@ protected boolean takeFluidInputs(MachineRecipe recipe, boolean simulate) {
return ok;
}

private boolean fluidIngredientMatch(FluidVariant resource, FluidIngredient ingredient) {
if (ingredient.isSimple()) {
for (var stack : ingredient.getStacks()) {
return resource.equals(FluidVariant.of(stack.getFluid()));
}
return false;
} else {
return ingredient.test(resource.toStack(1));
}
}

protected boolean putItemOutputs(MachineRecipe recipe, boolean simulate, boolean toggleLock) {
List<ConfigurableItemStack> baseList = inventory.getItemOutputs();
List<ConfigurableItemStack> stacks = simulate ? ConfigurableItemStack.copyList(baseList) : baseList;
Expand Down Expand Up @@ -682,10 +696,38 @@ public void lockRecipe(ResourceLocation recipeId, net.minecraft.world.entity.pla
// FLUID INPUTS
outer: for (MachineRecipe.FluidInput input : recipe.value().fluidInputs) {
for (ConfigurableFluidStack stack : this.inventory.getFluidInputs()) {
if (stack.isLockedTo(input.fluid()))
if (stack.getLockedInstance() != null && input.fluid().test(new FluidStack(stack.getLockedInstance(), 1)))
continue outer;
}
AbstractConfigurableStack.playerLockNoOverride(input.fluid(), this.inventory.getFluidInputs());
Fluid targetFluid = null;
// Find the first match in the player inventory
for (int i = 0; i < inventory.getContainerSize(); i++) {
var playerStack = FluidUtil.getFluidContained(inventory.getItem(i)).orElse(FluidStack.EMPTY);
if (!playerStack.isEmpty() && input.fluid().test(new FluidStack(playerStack.getFluid(), 1))) {
targetFluid = playerStack.getFluid();
break;
}
}
if (targetFluid == null) {
// Find the first match that is an item from MI
for (Fluid fluid : input.getInputFluids()) {
ResourceLocation id = BuiltInRegistries.FLUID.getKey(fluid);
if (id.getNamespace().equals(MI.ID)) {
targetFluid = fluid;
break;
}
}
}
if (targetFluid == null) {
// If there is only one value in the tag, pick that one
if (input.getInputFluids().size() == 1) {
targetFluid = input.getInputFluids().get(0);
}
}

if (targetFluid != null) {
AbstractConfigurableStack.playerLockNoOverride(targetFluid, this.inventory.getFluidInputs());
}
}
// FLUID OUTPUTS
outer: for (MachineRecipe.FluidOutput output : recipe.value().fluidOutputs) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import net.minecraft.world.item.crafting.ShapedRecipe;
import net.minecraft.world.level.ItemLike;
import net.minecraft.world.level.material.Fluid;
import net.neoforged.neoforge.fluids.crafting.FluidIngredient;

@SuppressWarnings({ "FieldCanBeLocal", "unused", "MismatchedQueryAndUpdateOfCollection" })
public class MIRecipeJson<T extends MIRecipeJson<?>> {
Expand Down Expand Up @@ -149,7 +150,7 @@ public T addFluidInput(Fluid fluid, int amount, float probability) {
if (id.equals(BuiltInRegistries.FLUID.getDefaultKey())) {
throw new RuntimeException("Could not find id for fluid " + fluid);
}
recipe.fluidInputs.add(new MachineRecipe.FluidInput(fluid, amount, probability));
recipe.fluidInputs.add(new MachineRecipe.FluidInput(FluidIngredient.of(fluid), amount, probability));
return (T) this;
}

Expand Down
Loading
Loading