Skip to content

Commit

Permalink
feat: make vats not accept ingredients if there are already ingredien…
Browse files Browse the repository at this point in the history
…ts of another recipe present
  • Loading branch information
klikli-dev committed Aug 20, 2024
1 parent c2af7ad commit ff60029
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package com.klikli_dev.theurgy.content.apparatus.digestionvat;

import com.klikli_dev.theurgy.content.recipe.DigestionRecipe;
import com.klikli_dev.theurgy.content.recipe.FermentationRecipe;
import com.klikli_dev.theurgy.content.recipe.input.ItemHandlerWithFluidRecipeInput;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack;
Expand All @@ -15,6 +16,7 @@
import net.neoforged.neoforge.fluids.FluidStack;
import org.jetbrains.annotations.Nullable;

import java.util.Collection;
import java.util.Optional;

/**
Expand All @@ -32,6 +34,29 @@ public DigestionCachedCheck(RecipeType<DigestionRecipe> type) {
this.internal = RecipeManager.createCheck(type);
}

private boolean matchesRecipe(RecipeHolder<DigestionRecipe> recipe, Collection<ItemStack> input) {
var ingredients = recipe.value().getIngredients();

// Check if every input ItemStack matches at least one ingredient in the recipe
return input.stream().allMatch(stack ->
ingredients.stream().anyMatch(ingredient -> ingredient.test(stack))
);
}

private Optional<RecipeHolder<DigestionRecipe>> getRecipeFor(Collection<ItemStack> input, Level level, @Nullable ResourceLocation lastRecipe) {
var recipeManager = level.getRecipeManager();

if (lastRecipe != null) {
var recipe = recipeManager.byKeyTyped(this.type, lastRecipe);
//test only the ingredient without the (separate) fluid ingredient check that the recipe.matches() would.
if (recipe != null && this.matchesRecipe(recipe, input)) {
return Optional.of(recipe);
}
}

return recipeManager.byType(this.type).stream().filter((entry) -> this.matchesRecipe(entry, input)).findFirst();
}

private Optional<RecipeHolder<DigestionRecipe>> getRecipeFor(ItemStack stack, Level level, @Nullable ResourceLocation lastRecipe) {
var recipeManager = level.getRecipeManager();
if (lastRecipe != null) {
Expand Down Expand Up @@ -60,6 +85,21 @@ private Optional<RecipeHolder<DigestionRecipe>> getRecipeFor(FluidStack stack, L
return recipeManager.byType(this.type).stream().filter((entry) -> entry.value().getFluid().ingredient().test(stack)).findFirst();
}


/**
* This only checks ingredients, including ingredients already present, not fluids
*/
public Optional<RecipeHolder<DigestionRecipe>> getRecipeFor(Collection<ItemStack> input, Level level) {
var optional = this.getRecipeFor(input, level, this.lastRecipe);
if (optional.isPresent()) {
var recipeHolder = optional.get();
this.lastRecipe = recipeHolder.id();
return optional;
} else {
return Optional.empty();
}
}

/**
* This only checks ingredients, not fluids
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

import java.util.Objects;
import java.util.function.Supplier;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class DigestionCraftingBehaviour extends CraftingBehaviour<ItemHandlerWithFluidRecipeInput, DigestionRecipe, DigestionCachedCheck> {

Expand All @@ -34,6 +36,31 @@ public DigestionCraftingBehaviour(BlockEntity blockEntity, Supplier<IItemHandler
this.fluidTankSupplier = fluidTankSupplier;
}

@Override
public boolean canProcess(ItemStack stack) {
if (this.alreadyHasInput(stack))
return true; //early out if we are already processing this type of item

var currentRecipe = this.getRecipe();
if (currentRecipe.isPresent()) {
//if we currently have a recipe we determine process-ability based on if the item is part of the recipe
return currentRecipe.get().value().getIngredients().stream().anyMatch(ingredient -> ingredient.test(stack));
}

var ingredientsList = Stream.concat(
IntStream.range(0, this.inputInventorySupplier.get().getSlots()).filter(i -> !this.inputInventorySupplier.get().getStackInSlot(i).isEmpty()).mapToObj(i -> this.inputInventorySupplier.get().getStackInSlot(i)),
Stream.of(stack)
).toList();

if (ingredientsList.size() > 1) {
//if we have any items in the input inventory (= more simulated ingredients than one, which is the one we are checking), we can only process items that share a recipe with already existing items
return this.recipeCachedCheck.getRecipeFor(ingredientsList, this.blockEntity.getLevel()).isPresent();
}

//finally if we have an empty inventory we do a simple check if the item is an ingredient of any recipe
return this.isIngredient(stack);
}

@Override
public boolean isIngredient(ItemStack stack) {
return this.recipeCachedCheck.getRecipeFor(stack, this.blockEntity.getLevel()).isPresent();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,16 @@
import net.minecraft.world.item.crafting.RecipeType;
import net.minecraft.world.level.Level;
import net.neoforged.neoforge.fluids.FluidStack;
import net.neoforged.neoforge.items.IItemHandlerModifiable;
import org.jetbrains.annotations.Nullable;

import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/**
* A custom cached check
Expand All @@ -32,6 +39,29 @@ public FermentationCachedCheck(RecipeType<FermentationRecipe> type) {
this.internal = RecipeManager.createCheck(type);
}

private boolean matchesRecipe(RecipeHolder<FermentationRecipe> recipe, Collection<ItemStack> input) {
var ingredients = recipe.value().getIngredients();

// Check if every input ItemStack matches at least one ingredient in the recipe
return input.stream().allMatch(stack ->
ingredients.stream().anyMatch(ingredient -> ingredient.test(stack))
);
}

private Optional<RecipeHolder<FermentationRecipe>> getRecipeFor(Collection<ItemStack> input, Level level, @Nullable ResourceLocation lastRecipe) {
var recipeManager = level.getRecipeManager();

if (lastRecipe != null) {
var recipe = recipeManager.byKeyTyped(this.type, lastRecipe);
//test only the ingredient without the (separate) fluid ingredient check that the recipe.matches() would.
if (recipe != null && this.matchesRecipe(recipe, input)) {
return Optional.of(recipe);
}
}

return recipeManager.byType(this.type).stream().filter((entry) -> this.matchesRecipe(entry, input)).findFirst();
}

private Optional<RecipeHolder<FermentationRecipe>> getRecipeFor(ItemStack stack, Level level, @Nullable ResourceLocation lastRecipe) {
var recipeManager = level.getRecipeManager();
if (lastRecipe != null) {
Expand Down Expand Up @@ -60,6 +90,20 @@ private Optional<RecipeHolder<FermentationRecipe>> getRecipeFor(FluidStack stack
return recipeManager.byType(this.type).stream().filter((entry) -> entry.value().getFluid().ingredient().test(stack)).findFirst();
}

/**
* This only checks ingredients, including ingredients already present, not fluids
*/
public Optional<RecipeHolder<FermentationRecipe>> getRecipeFor(Collection<ItemStack> input, Level level) {
var optional = this.getRecipeFor(input, level, this.lastRecipe);
if (optional.isPresent()) {
var recipeHolder = optional.get();
this.lastRecipe = recipeHolder.id();
return optional;
} else {
return Optional.empty();
}
}

/**
* This only checks ingredients, not fluids
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
import net.neoforged.neoforge.items.ItemHandlerHelper;

import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class FermentationCraftingBehaviour extends CraftingBehaviour<ItemHandlerWithFluidRecipeInput, FermentationRecipe, FermentationCachedCheck> {

Expand All @@ -33,6 +36,31 @@ public FermentationCraftingBehaviour(BlockEntity blockEntity, Supplier<IItemHand
this.fluidTankSupplier = fluidTankSupplier;
}

@Override
public boolean canProcess(ItemStack stack) {
if (this.alreadyHasInput(stack))
return true; //early out if we are already processing this type of item

var currentRecipe = this.getRecipe();
if (currentRecipe.isPresent()) {
//if we currently have a recipe we determine process-ability based on if the item is part of the recipe
return currentRecipe.get().value().getIngredients().stream().anyMatch(ingredient -> ingredient.test(stack));
}

var ingredientsList = Stream.concat(
IntStream.range(0, this.inputInventorySupplier.get().getSlots()).filter(i -> !this.inputInventorySupplier.get().getStackInSlot(i).isEmpty()).mapToObj(i -> this.inputInventorySupplier.get().getStackInSlot(i)),
Stream.of(stack)
).toList();

if (ingredientsList.size() > 1) {
//if we have any items in the input inventory (= more simulated ingredients than one, which is the one we are checking), we can only process items that share a recipe with already existing items
return this.recipeCachedCheck.getRecipeFor(ingredientsList, this.blockEntity.getLevel()).isPresent();
}

//finally if we have an empty inventory we do a simple check if the item is an ingredient of any recipe
return this.isIngredient(stack);
}

@Override
public boolean isIngredient(ItemStack stack) {
return this.recipeCachedCheck.getRecipeFor(stack, this.blockEntity.getLevel()).isPresent();
Expand Down

0 comments on commit ff60029

Please sign in to comment.