Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -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:
*
*<p>
* (A sub list means that <b>one</b> of its elements can be used.)
*
*
* <ul>
* <li>Optional: A {@link ResourceLocation} that serves as the recipe id.</li>
* <li>Optional: A {@link RecipeCategory}. Defaults to {@link RecipeCategory#MISC}</li>
* <ul>
* <li>An {@link ItemLike} for the output optionally followed by an {@link Integer} for the amount.</li>
* <li>An {@link ItemStack} that is used to determine the output item and count.</li>
* <li>An {@link ItemLike} for the output, optionally followed by an {@link Integer} for the amount.</li>
* <li>An {@link ItemStack} whose item and count form the output.</li>
* </ul>
* <li>A set of strings which are the pattern lines for the recipe.</li>
* <li>The rest of the input must be a {@link Character} followed by an ingredient identifier repeated for each key from the pattern lines.</li>
* <li>One or more {@code String}s that form the pattern lines of the recipe.</li>
* <li>For every non-space character used in the pattern: the {@link Character} itself followed by the ingredient identifier that defines that key.</li>
* <li>Optional: One or more {@code ICondition}s as conditions for the recipe.</li>
* </ul>
*
*
* An ingredient identifier is one of the following:
*
*
* <ul>
* <li>An {@link ItemLike}</li>
* <li>An {@link TagKey TagKey&lt;Item&gt;}</li>
* <li>A {@link TagKey TagKey&lt;Item&gt;}</li>
* <li>An {@link Ingredient}</li>
* <li>A list of the ones above.</li>
* </ul>
Expand All @@ -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:
*
* <p>
* (A sub list means that <b>one</b> of its elements can be used.)
*
* <ul>
* <li>Optional: A {@link ResourceLocation} that serves as the recipe id.</li>
* <li>Optional: A {@link RecipeCategory}. Defaults to {@link RecipeCategory#MISC}</li>
* <ul>
* <li>An {@link ItemLike} for the output optionally followed by an {@link Integer} for the amount.</li>
* <li>An {@link ItemStack} that is used to determine the output item and count.</li>
* <li>An {@link ItemLike} for the output, optionally followed by an {@link Integer} for the amount.</li>
* <li>An {@link ItemStack} whose item and count form the output.</li>
* </ul>
* <li>The rest of the input must be ingredient identifiers which set the required items.</li>
* <li>One or more ingredient identifiers that make up the recipe inputs.</li>
* <li>Optional: One or more {@code ICondition}s as conditions for the recipe.</li>
* </ul>
*
* An ingredient identifier is one of the following:
*
* <ul>
* <li>An {@link ItemLike}</li>
* <li>An {@link TagKey TagKey&lt;Item&gt;}</li>
* <li>A {@link TagKey TagKey&lt;Item&gt;}</li>
* <li>An {@link Ingredient}</li>
* <li>A list of the ones above.</li>
* </ul>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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<ICondition> 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) {
Expand All @@ -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<ICondition> conditions = consumeConditions(reader);
if (!conditions.isEmpty()) {
recipeOutput = recipeOutput.withConditions(conditions.toArray(ICondition[]::new));
}
builder.save(recipeOutput, id);
}

@Nullable
Expand All @@ -59,6 +72,25 @@ private static RecipeCategory getRecipeCategory(ObjectReader reader) {
return reader.optConsume(RecipeCategory.class).orElse(RecipeCategory.MISC);
}

@Nonnull
private static List<ICondition> consumeConditions(ObjectReader reader) {
List<ICondition> 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) {
Expand All @@ -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);
Expand Down Expand Up @@ -118,7 +155,7 @@ private static Ingredient createTagIngredient(TagKey<?> key) {
//noinspection unchecked
return Ingredient.of((TagKey<Item>) key);
}

@SafeVarargs
private static <T> Optional<T> first(Supplier<Optional<T>>... values) {
for (Supplier<Optional<T>> value : values) {
Expand Down Expand Up @@ -215,7 +252,7 @@ public <T> List<T> consumeWhile(Class<T> cls) {
}
}
}

@Nonnull
@SuppressWarnings("UnusedReturnValue")
public Object consume() {
Expand Down