Skip to content

Commit

Permalink
lazy cooking recipe conversion with automatic fluid detection (#99)
Browse files Browse the repository at this point in the history
  • Loading branch information
PssbleTrngle authored Aug 3, 2023
1 parent 0e956a6 commit 37fec21
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 89 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,13 @@ import com.possible_triangle.sliceanddice.SliceAndDice
import com.possible_triangle.sliceanddice.config.Configs
import com.possible_triangle.sliceanddice.recipe.CuttingProcessingRecipe
import com.simibubi.create.content.fluids.transfer.EmptyingRecipe
import com.simibubi.create.content.kinetics.mixer.MixingRecipe
import com.simibubi.create.content.processing.recipe.HeatCondition
import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder
import com.simibubi.create.foundation.fluid.FluidIngredient
import mezz.jei.api.registration.IRecipeCatalystRegistration
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.crafting.Ingredient
import net.minecraft.world.item.crafting.Recipe
import net.minecraftforge.fluids.FluidStack
import vectorwing.farmersdelight.common.crafting.CookingPotRecipe
import vectorwing.farmersdelight.common.crafting.CuttingBoardRecipe
import vectorwing.farmersdelight.integration.jei.FDRecipeTypes
Expand Down Expand Up @@ -78,29 +75,14 @@ class FarmersDelightCompat private constructor() : IRecipeInjector {

SliceAndDice.LOGGER.debug("Found {} cooking recipes", cookingRecipes.size)

fun fluidOf(ingredient: Ingredient): FluidStack? {
if (!Configs.SERVER.REPLACE_FLUID_CONTAINERS.get()) return null
val cloned = Ingredient.fromJson(ingredient.toJson())
val fluids = cloned.items.mapNotNull { stack ->
emptyingRecipes.find {
val required = it.ingredients[0]
required.test(stack)
}?.resultingFluid
}

return fluids.minByOrNull { it.amount }
}

return cookingRecipes.forEach { (originalID, recipe) ->
val id = ResourceLocation(SliceAndDice.MOD_ID, "cooking/${originalID.namespace}/${originalID.path}")
val builder = ProcessingRecipeBuilder(::MixingRecipe, id)
val builder = ProcessingRecipeBuilder(::LazyMixingRecipe, id)
builder.duration(recipe.cookTime)
builder.requiresHeat(HeatCondition.HEATED)

recipe.ingredients.forEach { ingredient ->
val fluid = fluidOf(ingredient)
if (fluid != null) builder.require(FluidIngredient.fromFluidStack(fluid))
else builder.require(ingredient)
builder.require(ingredient)
}

@Suppress("SENSELESS_COMPARISON")
Expand All @@ -109,7 +91,7 @@ class FarmersDelightCompat private constructor() : IRecipeInjector {
}

builder.output(recipe.resultItem)
add.accept(id, builder.build())
add.accept(id, builder.build().withRecipeLookup(emptyingRecipes))
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package com.possible_triangle.sliceanddice.compat

import com.possible_triangle.sliceanddice.config.Configs
import com.simibubi.create.content.fluids.transfer.EmptyingRecipe
import com.simibubi.create.content.kinetics.mixer.MixingRecipe
import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder.ProcessingRecipeParams
import com.simibubi.create.foundation.fluid.FluidIngredient
import net.minecraft.core.NonNullList
import net.minecraft.world.item.crafting.Ingredient
import net.minecraftforge.fluids.FluidStack

private fun <T> Collection<T>.toNonnullList() = let {
NonNullList.createWithCapacity<T>(it.size).apply {
addAll(it)
}
}

class LazyMixingRecipe(params: ProcessingRecipeParams) : MixingRecipe(params) {

private var emptyingRecipes: Collection<EmptyingRecipe> = emptyList()
private var resolved = false
private lateinit var resolvedIngredients: NonNullList<Ingredient>
private lateinit var resolvedFluidIngredients: NonNullList<FluidIngredient>

fun withRecipeLookup(emptyingRecipes: Collection<EmptyingRecipe>) = apply {
this.emptyingRecipes = emptyingRecipes
}

private fun fluidOf(ingredient: Ingredient): FluidStack {
if (!Configs.SERVER.REPLACE_FLUID_CONTAINERS.get()) return FluidStack.EMPTY
val fluids = ingredient.items.mapNotNull { stack ->
emptyingRecipes.find {
val required = it.ingredients[0]
required.test(stack)
}?.resultingFluid
}

return fluids.minByOrNull { it.amount } ?: FluidStack.EMPTY
}

private fun resolve() {
if (resolved) return
val replaceable = super.ingredients
.associateWith { fluidOf(it) }
.filterValues { !it.isEmpty }
.mapValues { FluidIngredient.fromFluidStack(it.value) }

resolvedIngredients = super.ingredients.filterNot { replaceable.containsKey(it) }.toNonnullList()
resolvedFluidIngredients = (super.fluidIngredients + replaceable.values).toNonnullList()
resolved = true
}

override fun getIngredients(): NonNullList<Ingredient> {
resolve()
return resolvedIngredients
}

override fun getFluidIngredients(): NonNullList<FluidIngredient> {
resolve()
return resolvedFluidIngredients
}

}
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
package com.possible_triangle.sliceanddice.config

import net.minecraftforge.common.ForgeConfigSpec
import java.util.function.Supplier

class ServerConfig(builder: ForgeConfigSpec.Builder) {

val CONSUME_DURABILTY = builder.define("slicer.consume_tool_durability", true)
val IGNORE_ROTATION = builder.define("slicer.ignore_rotation", false)

val BASIN_COOKING = builder.define("basin_cooking.enabled", true)
//val REPLACE_FLUID_CONTAINERS = builder.define("basin_cooking.replace_fluid_containers", true)
val REPLACE_FLUID_CONTAINERS = Supplier { false }
val REPLACE_FLUID_CONTAINERS = builder.define("basin_cooking.replace_fluid_containers", true)

val SPRINKLER_CAPACITY = builder.defineInRange("sprinkler.fluid_capacity", 300, 10, 2048)
val SPRINKLER_USAGE = builder.defineInRange("sprinkler.fluid_per_use", 100, 0, 2048)
Expand Down

This file was deleted.

This file was deleted.

0 comments on commit 37fec21

Please sign in to comment.