Recipe backtracking

This commit is contained in:
DBotThePony 2022-11-09 19:46:44 +07:00
parent 36dcc83f35
commit caa5464641
Signed by: DBot
GPG Key ID: DCC23B5715498507

View File

@ -65,7 +65,19 @@ object RecipeResolverManager : SimpleJsonResourceReloadListener(GsonBuilder().se
* if we can't resolve one of ingredient's matter value - consider output also having no matter value
*/
val isCritical: Boolean = true,
val name: ResourceLocation? = null
val name: ResourceLocation? = null,
/**
* Whenever to allow "backtracking" recipe ingredients to recipe outputs.
*
* When an item has no recipes, but takes part in recipes with output of already determined matter value
* (e.g. 4 rabbit hides -> 1 leather), we can assume that we can determine matter value of ingredients based on matter value of output
*
* "Backtrack" can happen if everything of the next holds true:
* * All recipes with item in question contains only that item; and
* * All recipes allow backtracking
*/
val allowBacktrack: Boolean = true,
) {
val inputs: List<List<ImmutableStack>> = inputs
.map { it.filter { it.multiplier > 0.0 }.collect(ImmutableList.toImmutableList()) }
@ -92,6 +104,8 @@ object RecipeResolverManager : SimpleJsonResourceReloadListener(GsonBuilder().se
*
* Internally, OTM separate parallel streams from sequential so sequential streams happen strictly on server thread
* (if you can't avoid side effects, or don't bother with synchronization).
*
* You can safely call [MatterManager.getDirect] inside returned stream, both parallel and sequential.
*/
fun find(server: MinecraftServer, json: JsonObject): Stream<ResolvedRecipe>
}
@ -118,6 +132,7 @@ object RecipeResolverManager : SimpleJsonResourceReloadListener(GsonBuilder().se
val isCritical = data["is_critical"]?.asBoolean ?: true
val ignoreDamageables = data["ignore_damageables"]?.asBoolean ?: false
val allowBacktrack = data["allow_backtrack"]?.asBoolean ?: true
server.recipeManager.byType(findRecipeType).values.parallelStream()
.filter { !it.isIncomplete && !it.ingredients.stream().anyMatch { it.isActuallyEmpty } } // get rid of invalid recipes, second "isActuallyEmpty" is required because we do care about ingredients being "missing"
@ -129,7 +144,8 @@ object RecipeResolverManager : SimpleJsonResourceReloadListener(GsonBuilder().se
it.ingredients.stream().map { Arrays.stream(it.items).map { ImmutableStack(it) } },
ImmutableStack(it.resultItem),
isCritical = isCritical,
name = it.id
name = it.id,
allowBacktrack = allowBacktrack
)
}
.filter { it.inputs.isNotEmpty() }
@ -291,11 +307,47 @@ object RecipeResolverManager : SimpleJsonResourceReloadListener(GsonBuilder().se
val recipes = output2Recipes[item]
if (recipes == null) {
if (recipes == null || recipes.isEmpty()) {
val recipes2 = input2Recipes[item]
if (recipes2 == null || recipes2.isEmpty() || !recipes2.all { it.allowBacktrack } || !recipes2.all { it.inputs.all { it.all { it.item == item } } }) {
commentary[item] = TextComponent("Item '${item.registryName}' has no recipes")
return Result.MISSING
}
var minimal: IMatterValue? = null
var minimalMultiplier = 0.0
var foundRecipe: ResolvedRecipe? = null
for (recipe in recipes2) {
val value = MatterManager.getDirect(recipe.output.item)
if (value.hasMatterValue) {
if (minimal == null || minimal < value) {
minimal = value
minimalMultiplier = recipe.output.multiplier / recipe.inputs.size
foundRecipe = recipe
}
} else {
minimal = null
break
}
}
if (minimal == null) {
commentary[item] = TextComponent("Item '${item.registryName}' has no valid backtracking recipes, and no output recipes")
return Result.MISSING
}
val result = MatterValue(minimal.matter * minimalMultiplier, minimal.complexity * minimalMultiplier)
changes = true
determinedValues[item] = result
commentary[item] = TextComponent("Matter value backtracked from ${foundRecipe!!.formattedName}")
return Result(result)
}
var hadSkips = false
recipesLoop@ for (recipe in recipes) {