170 lines
5.7 KiB
Java
170 lines
5.7 KiB
Java
package org.betterx.bclib.recipes;
|
|
|
|
import org.betterx.bclib.BCLib;
|
|
import org.betterx.bclib.api.v3.datagen.DatapackRecipeBuilder;
|
|
import org.betterx.bclib.api.v3.datagen.RecipeDataProvider;
|
|
import org.betterx.bclib.util.RecipeHelper;
|
|
|
|
import net.minecraft.advancements.CriterionTriggerInstance;
|
|
import net.minecraft.advancements.critereon.InventoryChangeTrigger;
|
|
import net.minecraft.core.registries.BuiltInRegistries;
|
|
import net.minecraft.data.recipes.FinishedRecipe;
|
|
import net.minecraft.data.recipes.RecipeCategory;
|
|
import net.minecraft.data.recipes.RecipeProvider;
|
|
import net.minecraft.nbt.CompoundTag;
|
|
import net.minecraft.resources.ResourceLocation;
|
|
import net.minecraft.tags.TagKey;
|
|
import net.minecraft.world.item.Item;
|
|
import net.minecraft.world.item.ItemStack;
|
|
import net.minecraft.world.item.Items;
|
|
import net.minecraft.world.level.ItemLike;
|
|
import net.minecraft.world.level.block.Block;
|
|
|
|
import java.util.Arrays;
|
|
import java.util.function.Consumer;
|
|
import java.util.stream.Collectors;
|
|
|
|
public abstract class AbstractBaseRecipeBuilder<T extends AbstractBaseRecipeBuilder> implements DatapackRecipeBuilder {
|
|
protected final ResourceLocation id;
|
|
protected final ItemStack output;
|
|
protected String group;
|
|
|
|
protected RecipeCategory category;
|
|
|
|
protected boolean alright;
|
|
|
|
|
|
protected AbstractBaseRecipeBuilder(ResourceLocation id, ItemLike output) {
|
|
this.id = id;
|
|
this.output = new ItemStack(output, 1);
|
|
this.category = RecipeCategory.MISC;
|
|
this.alright = RecipeHelper.exists(output);
|
|
}
|
|
|
|
public T setCategory(RecipeCategory category) {
|
|
this.category = category;
|
|
return (T) this;
|
|
}
|
|
|
|
protected T setGroup(String group) {
|
|
this.group = group;
|
|
return (T) this;
|
|
}
|
|
|
|
protected T setOutputCount(int count) {
|
|
this.output.setCount(count);
|
|
return (T) this;
|
|
}
|
|
|
|
protected T setOutputTag(CompoundTag tag) {
|
|
this.output.setTag(tag);
|
|
return (T) this;
|
|
}
|
|
|
|
protected T unlockedBy(ItemLike item) {
|
|
this.unlocks(
|
|
"has_" + item.asItem().getDescriptionId(),
|
|
RecipeProvider.has(item.asItem())
|
|
);
|
|
|
|
return (T) this;
|
|
}
|
|
|
|
protected T unlockedBy(TagKey<Item> tag) {
|
|
this.unlocks(
|
|
"has_tag_" + tag.location().getNamespace() + "_" + tag.location().getPath(),
|
|
RecipeProvider.has(tag)
|
|
);
|
|
|
|
return (T) this;
|
|
}
|
|
|
|
/**
|
|
* The Recipe will be unlocked by one of the passed Items. As sonn als players have one in their Inventory
|
|
* the recipe will unlock. Those Items are mostly the input Items for the recipe.
|
|
* <p>
|
|
* This method will automatically derive a unique name for the criterion and call
|
|
* {@link #unlocks(String, ItemLike...)}
|
|
*
|
|
* @param items {@link Item}s or {@link Block}s that will unlock the recipe.
|
|
*/
|
|
protected T unlockedBy(ItemLike... items) {
|
|
String name = "has_" +
|
|
Arrays.stream(items)
|
|
.map(block -> (block instanceof Block)
|
|
? BuiltInRegistries.BLOCK.getKey((Block) block)
|
|
: BuiltInRegistries.ITEM.getKey((Item) block))
|
|
.filter(id -> id != null)
|
|
.map(id -> id.getPath())
|
|
.collect(Collectors.joining("_"));
|
|
if (name.length() > 45) name = name.substring(0, 42);
|
|
return unlocks(name, items);
|
|
}
|
|
|
|
/**
|
|
* The Recipe will be unlocked by one of the passed Items. As sonn als players have one in their Inventory
|
|
* the recipe will unlock. Those Items are mostly the input Items for the recipe.
|
|
*
|
|
* @param name The name for this unlock-Criteria
|
|
* @param items {@link Item}s or {@link Block}s that will unlock the recipe.
|
|
*/
|
|
protected T unlocks(String name, ItemLike... items) {
|
|
return unlocks(name, InventoryChangeTrigger.TriggerInstance.hasItems(items));
|
|
}
|
|
|
|
/**
|
|
* The Recipe will be unlocked by one of the passed Items. As sonn als players have one in their Inventory
|
|
* the recipe will unlock. Those Items are mostly the input Items for the recipe.
|
|
* <p>
|
|
* This method will automatically get the Items from the stacl and call {@link #unlockedBy(ItemLike...)}
|
|
*
|
|
* @param stacks {@link ItemStack}s that will unlock the recipe. The count is ignored.
|
|
*/
|
|
protected T unlockedBy(ItemStack... stacks) {
|
|
ItemLike[] items = Arrays.stream(stacks)
|
|
.filter(stack -> stack.getCount() > 0)
|
|
.map(stack -> (ItemLike) stack.getItem())
|
|
.toArray(ItemLike[]::new);
|
|
|
|
return unlockedBy(items);
|
|
}
|
|
|
|
protected abstract T unlocks(String name, CriterionTriggerInstance trigger);
|
|
|
|
|
|
public final T build() {
|
|
if (!checkRecipe())
|
|
return (T) this;
|
|
RecipeDataProvider.register(this);
|
|
return (T) this;
|
|
}
|
|
|
|
protected boolean checkRecipe() {
|
|
if (output == null) {
|
|
BCLib.LOGGER.warning("Output for Recipe can't be 'null', recipe {} will be ignored!", id);
|
|
return false;
|
|
}
|
|
if (output.is(Items.AIR)) {
|
|
BCLib.LOGGER.warning("Unable to build Recipe " + id + ": Result is AIR");
|
|
return false;
|
|
}
|
|
if (!alright) {
|
|
BCLib.LOGGER.debug("Can't add recipe {}! Ingeredient or output do not exists.", id);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
protected abstract void buildRecipe(Consumer<FinishedRecipe> cc);
|
|
|
|
@Override
|
|
public final void build(Consumer<FinishedRecipe> cc) {
|
|
if (!checkRecipe()) return;
|
|
buildRecipe(cc);
|
|
}
|
|
|
|
@Override
|
|
public final ResourceLocation getId() {
|
|
return id;
|
|
}
|
|
}
|