diff --git a/src/main/java/org/moddingx/libx/datagen/provider/recipe/crafting/CraftingExtension.java b/src/main/java/org/moddingx/libx/datagen/provider/recipe/crafting/CraftingExtension.java
index d97c71be..940eebde 100644
--- a/src/main/java/org/moddingx/libx/datagen/provider/recipe/crafting/CraftingExtension.java
+++ b/src/main/java/org/moddingx/libx/datagen/provider/recipe/crafting/CraftingExtension.java
@@ -17,25 +17,26 @@ public interface CraftingExtension extends RecipeExtension {
/**
* Adds a new shaped recipe based on the input objects. The input objects must
* be built like this:
- *
+ *
* (A sub list means that one of its elements can be used.)
- *
+ *
*
* - Optional: A {@link ResourceLocation} that serves as the recipe id.
* - Optional: A {@link RecipeCategory}. Defaults to {@link RecipeCategory#MISC}
*
- * - An {@link ItemLike} for the output optionally followed by an {@link Integer} for the amount.
- * - An {@link ItemStack} that is used to determine the output item and count.
+ * - An {@link ItemLike} for the output, optionally followed by an {@link Integer} for the amount.
+ * - An {@link ItemStack} whose item and count form the output.
*
- * - A set of strings which are the pattern lines for the recipe.
- * - The rest of the input must be a {@link Character} followed by an ingredient identifier repeated for each key from the pattern lines.
+ * - One or more {@code String}s that form the pattern lines of the recipe.
+ * - For every non-space character used in the pattern: the {@link Character} itself followed by the ingredient identifier that defines that key.
+ * - Optional: One or more {@code ICondition}s as conditions for the recipe.
*
- *
+ *
* An ingredient identifier is one of the following:
- *
+ *
*
* - An {@link ItemLike}
- * - An {@link TagKey TagKey<Item>}
+ * - A {@link TagKey TagKey<Item>}
* - An {@link Ingredient}
* - A list of the ones above.
*
@@ -47,23 +48,25 @@ default void shaped(Object... objects) {
/**
* Adds a new shapeless recipe based on the input objects. The input objects must
* be built like this:
- *
+ *
* (A sub list means that one of its elements can be used.)
*
*
* - Optional: A {@link ResourceLocation} that serves as the recipe id.
+ * - Optional: A {@link RecipeCategory}. Defaults to {@link RecipeCategory#MISC}
*
- * - An {@link ItemLike} for the output optionally followed by an {@link Integer} for the amount.
- * - An {@link ItemStack} that is used to determine the output item and count.
+ * - An {@link ItemLike} for the output, optionally followed by an {@link Integer} for the amount.
+ * - An {@link ItemStack} whose item and count form the output.
*
- * - The rest of the input must be ingredient identifiers which set the required items.
+ * - One or more ingredient identifiers that make up the recipe inputs.
+ * - Optional: One or more {@code ICondition}s as conditions for the recipe.
*
*
* An ingredient identifier is one of the following:
*
*
* - An {@link ItemLike}
- * - An {@link TagKey TagKey<Item>}
+ * - A {@link TagKey TagKey<Item>}
* - An {@link Ingredient}
* - A list of the ones above.
*
diff --git a/src/main/java/org/moddingx/libx/impl/datagen/recipe/ObjectCraftingBuilder.java b/src/main/java/org/moddingx/libx/impl/datagen/recipe/ObjectCraftingBuilder.java
index a909ce04..55efb31d 100644
--- a/src/main/java/org/moddingx/libx/impl/datagen/recipe/ObjectCraftingBuilder.java
+++ b/src/main/java/org/moddingx/libx/impl/datagen/recipe/ObjectCraftingBuilder.java
@@ -3,6 +3,7 @@
import net.minecraft.advancements.Criterion;
import net.minecraft.core.registries.Registries;
import net.minecraft.data.recipes.RecipeCategory;
+import net.minecraft.data.recipes.RecipeOutput;
import net.minecraft.data.recipes.ShapedRecipeBuilder;
import net.minecraft.data.recipes.ShapelessRecipeBuilder;
import net.minecraft.resources.ResourceLocation;
@@ -11,12 +12,14 @@
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.level.ItemLike;
+import net.neoforged.neoforge.common.conditions.ICondition;
import net.neoforged.neoforge.common.crafting.CompoundIngredient;
import org.moddingx.libx.datagen.provider.recipe.RecipeExtension;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.function.BiConsumer;
@@ -35,7 +38,12 @@ public static void buildShaped(RecipeExtension ext, Object[] objects) {
builder.pattern(line);
}
addShapedIngredients(ext, builder, reader);
- builder.save(ext.output(), id);
+ RecipeOutput recipeOutput = ext.output();
+ List conditions = consumeConditions(reader);
+ if (!conditions.isEmpty()) {
+ recipeOutput = recipeOutput.withConditions(conditions.toArray(ICondition[]::new));
+ }
+ builder.save(recipeOutput, id);
}
public static void buildShapeless(RecipeExtension ext, Object[] objects) {
@@ -46,7 +54,12 @@ public static void buildShapeless(RecipeExtension ext, Object[] objects) {
if (id == null) id = ext.provider().loc(output.getItem());
ShapelessRecipeBuilder builder = ShapelessRecipeBuilder.shapeless(recipeCategory, output);
addShapelessIngredients(ext, builder, reader);
- builder.save(ext.output(), id);
+ RecipeOutput recipeOutput = ext.output();
+ List conditions = consumeConditions(reader);
+ if (!conditions.isEmpty()) {
+ recipeOutput = recipeOutput.withConditions(conditions.toArray(ICondition[]::new));
+ }
+ builder.save(recipeOutput, id);
}
@Nullable
@@ -59,6 +72,25 @@ private static RecipeCategory getRecipeCategory(ObjectReader reader) {
return reader.optConsume(RecipeCategory.class).orElse(RecipeCategory.MISC);
}
+ @Nonnull
+ private static List consumeConditions(ObjectReader reader) {
+ List conditions = new ArrayList<>();
+ while (reader.hasNext()) {
+ Object next = reader.peek();
+ if (next instanceof ICondition condition) {
+ reader.consume();
+ conditions.add(condition);
+ } else if (next instanceof ICondition[] conditionArray) {
+ reader.consume();
+ conditions.addAll(List.of(conditionArray));
+ } else {
+ break;
+ }
+ }
+
+ return conditions;
+ }
+
private static void addShapedIngredients(RecipeExtension ext, ShapedRecipeBuilder builder, ObjectReader reader) {
int nextId = 0;
while (true) {
@@ -77,6 +109,11 @@ private static void addShapedIngredients(RecipeExtension ext, ShapedRecipeBuilde
private static void addShapelessIngredients(RecipeExtension ext, ShapelessRecipeBuilder builder, ObjectReader reader) {
int nextId = 0;
while (reader.hasNext()) {
+ Object peek = reader.peek();
+ if (peek instanceof ICondition || peek instanceof ICondition[]) {
+ break;
+ }
+
Ingredient ingredient = getIngredient(reader);
builder.requires(ingredient);
nextId = addCriteriaToBuilder(builder::unlockedBy, ext.criteria(ingredient), nextId);
@@ -118,7 +155,7 @@ private static Ingredient createTagIngredient(TagKey> key) {
//noinspection unchecked
return Ingredient.of((TagKey- ) key);
}
-
+
@SafeVarargs
private static Optional first(Supplier>... values) {
for (Supplier> value : values) {
@@ -215,7 +252,7 @@ public List consumeWhile(Class cls) {
}
}
}
-
+
@Nonnull
@SuppressWarnings("UnusedReturnValue")
public Object consume() {