[Change] Recipe Handling moved to Datagen
This commit is contained in:
parent
f60fcd02d5
commit
809bfddd32
28 changed files with 1279 additions and 1121 deletions
|
@ -0,0 +1,15 @@
|
|||
package org.betterx.bclib.api.v3.datagen;
|
||||
|
||||
import net.minecraft.data.recipes.FinishedRecipe;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public interface DatapackRecipeBuilder {
|
||||
ResourceLocation getId();
|
||||
|
||||
default String getNamespace() {
|
||||
return this.getId().getNamespace();
|
||||
}
|
||||
void build(Consumer<FinishedRecipe> cc);
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package org.betterx.bclib.api.v3.datagen;
|
||||
|
||||
import net.minecraft.data.recipes.FinishedRecipe;
|
||||
|
||||
import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
|
||||
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class RecipeDataProvider extends FabricRecipeProvider {
|
||||
private static List<DatapackRecipeBuilder> RECIPES;
|
||||
|
||||
@Nullable
|
||||
protected final List<String> modIDs;
|
||||
|
||||
public RecipeDataProvider(@Nullable List<String> modIDs, FabricDataOutput output) {
|
||||
super(output);
|
||||
this.modIDs = modIDs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildRecipes(Consumer<FinishedRecipe> exporter) {
|
||||
if (RECIPES == null) return;
|
||||
|
||||
for (var r : RECIPES) {
|
||||
if (modIDs.size() == 0 || modIDs.indexOf(r.getNamespace()) >= 0) {
|
||||
r.build(exporter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static void register(DatapackRecipeBuilder builder) {
|
||||
if (RECIPES == null) RECIPES = new ArrayList<>();
|
||||
RECIPES.add(builder);
|
||||
}
|
||||
}
|
|
@ -270,7 +270,7 @@ public class WoodenComplexMaterial extends ComplexMaterial {
|
|||
BCLRecipeBuilder.crafting(id, planks)
|
||||
.checkConfig(config)
|
||||
.setOutputCount(4)
|
||||
.setList("#")
|
||||
.shapeless()
|
||||
.addMaterial('#', log, bark, log_stripped, bark_stripped)
|
||||
.setGroup(receipGroupPrefix + "_planks")
|
||||
.build();
|
||||
|
@ -315,7 +315,7 @@ public class WoodenComplexMaterial extends ComplexMaterial {
|
|||
addRecipeEntry(new RecipeEntry("button", (material, config, id) -> {
|
||||
BCLRecipeBuilder.crafting(id, getBlock(BLOCK_BUTTON))
|
||||
.checkConfig(config)
|
||||
.setList("#")
|
||||
.shapeless()
|
||||
.addMaterial('#', planks)
|
||||
.setGroup(receipGroupPrefix + "_planks_buttons")
|
||||
.build();
|
||||
|
|
|
@ -2,7 +2,7 @@ package org.betterx.bclib.items.complex;
|
|||
|
||||
import org.betterx.bclib.items.BaseArmorItem;
|
||||
import org.betterx.bclib.recipes.BCLRecipeBuilder;
|
||||
import org.betterx.bclib.recipes.GridRecipe;
|
||||
import org.betterx.bclib.recipes.CraftingRecipeBuilder;
|
||||
import org.betterx.bclib.registry.ItemRegistry;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
@ -45,7 +45,7 @@ public class EquipmentDescription<I extends Item> {
|
|||
|
||||
}
|
||||
|
||||
protected boolean buildRecipe(Item tool, ItemLike stick, GridRecipe builder) {
|
||||
protected boolean buildRecipe(Item tool, ItemLike stick, CraftingRecipeBuilder builder) {
|
||||
if (tool instanceof ShearsItem) {
|
||||
builder.setShape(" #", "# ");
|
||||
} else if (tool instanceof BaseArmorItem bai) {
|
||||
|
|
|
@ -1,220 +0,0 @@
|
|||
package org.betterx.bclib.recipes;
|
||||
|
||||
import org.betterx.bclib.api.v2.advancement.AdvancementManager;
|
||||
|
||||
import net.minecraft.advancements.RequirementsStrategy;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.item.ArmorItem;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.TieredItem;
|
||||
import net.minecraft.world.item.crafting.Recipe;
|
||||
import net.minecraft.world.level.ItemLike;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Simple extension class that allows Recipe-builders to automatically generated Recipe-Avancements.
|
||||
* <p>
|
||||
* Implementing classes need to call {@link #createAdvancement(ResourceLocation, boolean)} or
|
||||
* {@link #createAdvancement(ResourceLocation, ItemLike)} to enable an advncement and
|
||||
* {@link #registerAdvancement(Recipe)} to finalize and register the new Advancement.
|
||||
* <p>
|
||||
* After that the unlockedBy-Methods can bes used to add Items that will unlock the Recipe (and prompt the unlock)
|
||||
*/
|
||||
public class AbstractAdvancementRecipe {
|
||||
protected AdvancementManager.Builder advancement;
|
||||
boolean hasUnlockTrigger = false;
|
||||
boolean generateAdvancement = false;
|
||||
|
||||
/**
|
||||
* Your implementing class should call this method to prepare a new {@link AdvancementManager.Builder}
|
||||
* <p>
|
||||
* For Example {@link FurnaceRecipe} will call this in the
|
||||
* {@link FurnaceRecipe#make(ResourceLocation, ItemLike)}-Method
|
||||
*
|
||||
* @param id {@link ResourceLocation} for this advancement
|
||||
* @param isTool true, if this is registered for a tool
|
||||
*/
|
||||
protected void createAdvancement(ResourceLocation id, boolean isTool) {
|
||||
hasUnlockTrigger = false;
|
||||
generateAdvancement = true;
|
||||
advancement = AdvancementManager.Builder.create(
|
||||
id,
|
||||
isTool
|
||||
? AdvancementManager.AdvancementType.RECIPE_TOOL
|
||||
: AdvancementManager.AdvancementType.RECIPE_DECORATIONS
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Your implementing class should call this method to prepare a new {@link AdvancementManager.Builder}
|
||||
* <p>
|
||||
* For Example {@link GridRecipe} will call this in the {@link GridRecipe#make(ResourceLocation, ItemLike)}-Method.
|
||||
* <p>
|
||||
* This method will call {@link #createAdvancement(ResourceLocation, boolean)}. The output object is used to
|
||||
* determine wether or not this is a tool recipe.
|
||||
*
|
||||
* @param id {@link ResourceLocation} for this advancement
|
||||
* @param output Used to determine wether or not this is a tool recipe.
|
||||
*/
|
||||
protected void createAdvancement(ResourceLocation id, ItemLike output) {
|
||||
createAdvancement(id, (output.asItem() instanceof TieredItem || output.asItem() instanceof ArmorItem));
|
||||
}
|
||||
|
||||
private int nameCounter = 0;
|
||||
|
||||
/**
|
||||
* 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>
|
||||
* If you need to use other unlock-Criteria, you can get the {@link AdvancementManager.Builder}-Instance
|
||||
* using {@link #getAdvancementBuilder()}
|
||||
* <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.
|
||||
*/
|
||||
public void unlockedBy(ItemStack... stacks) {
|
||||
ItemLike[] items = Arrays.stream(stacks)
|
||||
.filter(stack -> stack.getCount() > 0)
|
||||
.map(stack -> (ItemLike) stack.getItem())
|
||||
.toArray(ItemLike[]::new);
|
||||
|
||||
unlockedBy(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>
|
||||
* If you need to use other unlock-Criteria, you can get the {@link AdvancementManager.Builder}-Instance
|
||||
* using {@link #getAdvancementBuilder()}
|
||||
* <p>
|
||||
* This method will automatically derive a unique name for the criterion and call
|
||||
* {@link #unlockedBy(String, ItemLike...)}
|
||||
*
|
||||
* @param items {@link Item}s or {@link Block}s that will unlock the recipe.
|
||||
*/
|
||||
public void unlockedBy(ItemLike... items) {
|
||||
String name = "has_" + (nameCounter++) + "_" +
|
||||
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);
|
||||
unlockedBy(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.
|
||||
* <p>
|
||||
* If you need to use other unlock-Criteria, you can get the {@link AdvancementManager.Builder}-Instance
|
||||
* using {@link #getAdvancementBuilder()}
|
||||
* <p>
|
||||
* This method will automatically derive a unique name for the criterion and call
|
||||
* {@link #unlockedBy(String, TagKey)}
|
||||
*
|
||||
* @param tag All items from this Tag will unlock the recipe
|
||||
*/
|
||||
public void unlockedBy(TagKey<Item> tag) {
|
||||
ResourceLocation id = tag.location();
|
||||
if (id != null) {
|
||||
unlockedBy("has_tag_" + id.getPath(), tag);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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>
|
||||
* If you need to use other unlock-Criteria, you can get the {@link AdvancementManager.Builder}-Instance
|
||||
* using {@link #getAdvancementBuilder()}
|
||||
*
|
||||
* @param name The name for this unlock-Criteria
|
||||
* @param items {@link Item}s or {@link Block}s that will unlock the recipe.
|
||||
*/
|
||||
public void unlockedBy(String name, ItemLike... items) {
|
||||
if (advancement != null) {
|
||||
hasUnlockTrigger = true;
|
||||
advancement.addInventoryChangedCriterion(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.
|
||||
* <p>
|
||||
* If you need to use other unlock-Criteria, you can get the {@link AdvancementManager.Builder}-Instance
|
||||
* using {@link #getAdvancementBuilder()}
|
||||
*
|
||||
* @param name The name for this unlock-Criteria
|
||||
* @param tag All items from this Tag will unlock the recipe
|
||||
*/
|
||||
public void unlockedBy(String name, TagKey<Item> tag) {
|
||||
if (advancement != null) {
|
||||
hasUnlockTrigger = true;
|
||||
advancement.addInventoryChangedCriterion(name, tag);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables the generation of an advancement
|
||||
*/
|
||||
public void noAdvancement() {
|
||||
generateAdvancement = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the advancement. This is usefully when you need more controll but the Recipe Builder
|
||||
* (like {@link GridRecipe} is automatically adding Items to the criterion list.
|
||||
*/
|
||||
public void resetAdvancement() {
|
||||
if (advancement != null)
|
||||
advancement = AdvancementManager.Builder.createEmptyCopy(advancement);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the underlying Builder Instance
|
||||
*
|
||||
* @return null or The underlying builder Instance
|
||||
*/
|
||||
public AdvancementManager.Builder getAdvancementBuilder() {
|
||||
return advancement;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Your implementing class should calls this method to finalize the advancement and register it.
|
||||
* <p>
|
||||
* For Example {@link GridRecipe} will call this in the {@link GridRecipe#build()}-Method
|
||||
*
|
||||
* @param recipe The generated recipe that need to be linked to the Advancement
|
||||
*/
|
||||
protected void registerAdvancement(Recipe<?> recipe, ItemLike icon) {
|
||||
if (hasUnlockTrigger && generateAdvancement && advancement != null) {
|
||||
advancement
|
||||
.startDisplay(icon)
|
||||
.hideFromChat()
|
||||
.hideToast()
|
||||
.endDisplay()
|
||||
.addRecipeUnlockCriterion("has_the_recipe", recipe)
|
||||
.startReward()
|
||||
.addRecipe(recipe.getId())
|
||||
.endReward()
|
||||
.requirements(RequirementsStrategy.OR);
|
||||
|
||||
advancement.build();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,173 @@
|
|||
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;
|
||||
if (id.toString().equals("betternether:mushroom_fir_taburet")) {
|
||||
System.out.println("betternether:mushroom_fir_taburet");
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
package org.betterx.bclib.recipes;
|
||||
|
||||
import org.betterx.bclib.BCLib;
|
||||
import org.betterx.bclib.util.ItemUtil;
|
||||
import org.betterx.bclib.util.RecipeHelper;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.Container;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.crafting.Ingredient;
|
||||
import net.minecraft.world.item.crafting.Recipe;
|
||||
import net.minecraft.world.level.ItemLike;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
public abstract class AbstractDoubleInputRecipeBuilder<T extends AbstractDoubleInputRecipeBuilder, R extends Recipe<? extends Container>> extends AbstractSingleInputRecipeBuilder<T, R> {
|
||||
protected Ingredient secondaryInput;
|
||||
|
||||
protected AbstractDoubleInputRecipeBuilder(
|
||||
ResourceLocation id,
|
||||
ItemLike output
|
||||
) {
|
||||
super(id, output);
|
||||
}
|
||||
|
||||
public T setSecondaryInput(ItemLike... inputs) {
|
||||
for (ItemLike item : inputs) {
|
||||
this.alright &= RecipeHelper.exists(item);
|
||||
}
|
||||
this.secondaryInput = Ingredient.of(inputs);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T setSecondaryInput(TagKey<Item> input) {
|
||||
this.secondaryInput = Ingredient.of(input);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T setSecondaryInputAndUnlock(TagKey<Item> input) {
|
||||
setPrimaryInput(input);
|
||||
this.unlockedBy(input);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T setSecondaryInputAndUnlock(ItemLike... inputs) {
|
||||
setSecondaryInput(inputs);
|
||||
for (ItemLike item : inputs) unlockedBy(item);
|
||||
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean checkRecipe() {
|
||||
if (secondaryInput == null) {
|
||||
BCLib.LOGGER.warning(
|
||||
"Secondary input for Recipe can't be 'null', recipe {} will be ignored!",
|
||||
id
|
||||
);
|
||||
return false;
|
||||
}
|
||||
return super.checkRecipe();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void serializeRecipeData(JsonObject root) {
|
||||
final JsonArray ingredients = new JsonArray();
|
||||
ingredients.add(primaryInput.toJson());
|
||||
ingredients.add(secondaryInput.toJson());
|
||||
root.add("ingredients", ingredients);
|
||||
|
||||
if (group != null && !group.isEmpty()) {
|
||||
root.addProperty("group", group);
|
||||
}
|
||||
|
||||
root.add("result", ItemUtil.toJsonRecipe(output));
|
||||
}
|
||||
}
|
|
@ -1,102 +0,0 @@
|
|||
package org.betterx.bclib.recipes;
|
||||
|
||||
import org.betterx.bclib.BCLib;
|
||||
import org.betterx.bclib.config.PathConfig;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.Container;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.crafting.Ingredient;
|
||||
import net.minecraft.world.item.crafting.Recipe;
|
||||
import net.minecraft.world.item.crafting.RecipeType;
|
||||
import net.minecraft.world.level.ItemLike;
|
||||
|
||||
public abstract class AbstractSimpleRecipe<T extends AbstractSimpleRecipe, C extends Container, R extends Recipe<C>> extends AbstractAdvancementRecipe {
|
||||
public final ResourceLocation id;
|
||||
protected String group;
|
||||
protected Ingredient input;
|
||||
protected ItemLike output;
|
||||
protected final String category;
|
||||
protected final RecipeType<R> type;
|
||||
protected int count;
|
||||
protected boolean exist;
|
||||
|
||||
|
||||
protected AbstractSimpleRecipe(ResourceLocation id, RecipeType<R> type, ItemLike output) {
|
||||
this(id, type, type.toString(), output);
|
||||
}
|
||||
|
||||
protected AbstractSimpleRecipe(ResourceLocation id, RecipeType<R> type, String category, ItemLike output) {
|
||||
this.id = id;
|
||||
this.group = "";
|
||||
this.exist = true;
|
||||
this.count = 1;
|
||||
this.output = output;
|
||||
|
||||
this.category = category;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
|
||||
protected T setInput(ItemLike in) {
|
||||
this.exist &= BCLRecipeManager.exists(in);
|
||||
this.input = Ingredient.of(in);
|
||||
unlockedBy(in);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
protected T setInput(TagKey<Item> in) {
|
||||
this.input = Ingredient.of(in);
|
||||
unlockedBy(in);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T setGroup(String group) {
|
||||
this.group = group;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T setOutputCount(int count) {
|
||||
this.count = count;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T checkConfig(PathConfig config) {
|
||||
exist &= config.getBoolean(category, id.getPath(), true);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
protected abstract R buildRecipe();
|
||||
|
||||
protected boolean hasErrors() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public final void build() {
|
||||
if (!exist) {
|
||||
BCLib.LOGGER.warning("Unable to build Recipe " + id);
|
||||
return;
|
||||
}
|
||||
|
||||
if (input == null || input.isEmpty()) {
|
||||
BCLib.LOGGER.warning("Unable to build Recipe " + id + ": No Input Material");
|
||||
return;
|
||||
}
|
||||
|
||||
if (output == null) {
|
||||
BCLib.LOGGER.warning("Result recipe can't be 'null', recipe {} will be ignored!", id);
|
||||
return;
|
||||
}
|
||||
if (BCLRecipeManager.getRecipe(type, id) != null) {
|
||||
BCLib.LOGGER.warning("Can't add Smithing recipe! Id {} already exists!", id);
|
||||
return;
|
||||
}
|
||||
|
||||
if (hasErrors()) return;
|
||||
|
||||
R recipe = buildRecipe();
|
||||
BCLRecipeManager.addRecipe(type, recipe);
|
||||
registerAdvancement(recipe, output);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package org.betterx.bclib.recipes;
|
||||
|
||||
import org.betterx.bclib.BCLib;
|
||||
import org.betterx.bclib.util.RecipeHelper;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.crafting.Ingredient;
|
||||
import net.minecraft.world.level.ItemLike;
|
||||
|
||||
public abstract class AbstractSimpleRecipeBuilder<T extends AbstractSimpleRecipeBuilder> extends AbstractBaseRecipeBuilder<T> {
|
||||
protected Ingredient primaryInput;
|
||||
|
||||
protected AbstractSimpleRecipeBuilder(ResourceLocation id, ItemLike output) {
|
||||
super(id, output);
|
||||
}
|
||||
|
||||
|
||||
public T setPrimaryInput(ItemLike... inputs) {
|
||||
for (ItemLike item : inputs) {
|
||||
this.alright &= RecipeHelper.exists(item);
|
||||
}
|
||||
this.primaryInput = Ingredient.of(inputs);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T setPrimaryInput(TagKey<Item> input) {
|
||||
this.primaryInput = Ingredient.of(input);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T setPrimaryInputAndUnlock(TagKey<Item> input) {
|
||||
setPrimaryInput(input);
|
||||
this.unlockedBy(input);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T setPrimaryInputAndUnlock(ItemLike... inputs) {
|
||||
setPrimaryInput(inputs);
|
||||
for (ItemLike item : inputs) unlockedBy(item);
|
||||
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
|
||||
protected boolean checkRecipe() {
|
||||
if (primaryInput == null) {
|
||||
BCLib.LOGGER.warning(
|
||||
"Primary input for Recipe can't be 'null', recipe {} will be ignored!",
|
||||
id
|
||||
);
|
||||
return false;
|
||||
}
|
||||
return super.checkRecipe();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
package org.betterx.bclib.recipes;
|
||||
|
||||
import org.betterx.bclib.util.ItemUtil;
|
||||
|
||||
import net.minecraft.advancements.Advancement;
|
||||
import net.minecraft.advancements.CriterionTriggerInstance;
|
||||
import net.minecraft.advancements.RequirementsStrategy;
|
||||
import net.minecraft.advancements.critereon.RecipeUnlockedTrigger;
|
||||
import net.minecraft.data.recipes.FinishedRecipe;
|
||||
import net.minecraft.data.recipes.RecipeBuilder;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.Container;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.crafting.Recipe;
|
||||
import net.minecraft.world.item.crafting.RecipeSerializer;
|
||||
import net.minecraft.world.level.ItemLike;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public abstract class AbstractSingleInputRecipeBuilder<T extends AbstractSingleInputRecipeBuilder, R extends Recipe<? extends Container>> extends AbstractSimpleRecipeBuilder<T> {
|
||||
protected final Advancement.Builder advancement;
|
||||
|
||||
|
||||
protected AbstractSingleInputRecipeBuilder(ResourceLocation id, ItemLike output) {
|
||||
super(id, output);
|
||||
this.advancement = Advancement.Builder.advancement();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T unlockedBy(ItemLike item) {
|
||||
return super.unlockedBy(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T unlockedBy(TagKey<Item> tag) {
|
||||
return super.unlockedBy(tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected T unlocks(String name, CriterionTriggerInstance trigger) {
|
||||
this.advancement.addCriterion(name, trigger);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void buildRecipe(Consumer<FinishedRecipe> cc) {
|
||||
setupAdvancementForResult();
|
||||
cc.accept(new AbstractSingleInputRecipeBuilder<T, R>.Result());
|
||||
}
|
||||
|
||||
protected abstract RecipeSerializer<R> getSerializer();
|
||||
|
||||
protected void serializeRecipeData(JsonObject root) {
|
||||
root.add("input", primaryInput.toJson());
|
||||
|
||||
if (group != null && !group.isEmpty()) {
|
||||
root.addProperty("group", group);
|
||||
}
|
||||
|
||||
root.add("result", ItemUtil.toJsonRecipe(output));
|
||||
}
|
||||
|
||||
protected void setupAdvancementForResult() {
|
||||
advancement.parent(RecipeBuilder.ROOT_RECIPE_ADVANCEMENT)
|
||||
.addCriterion("has_the_recipe", RecipeUnlockedTrigger.unlocked(id))
|
||||
.rewards(net.minecraft.advancements.AdvancementRewards.Builder.recipe(id))
|
||||
.requirements(RequirementsStrategy.OR);
|
||||
}
|
||||
|
||||
protected ResourceLocation createAdvancementId() {
|
||||
return id.withPrefix("recipes/" + category.getFolderName() + "/");
|
||||
}
|
||||
|
||||
public class Result implements FinishedRecipe {
|
||||
private final ResourceLocation advancementId;
|
||||
|
||||
protected Result() {
|
||||
this.advancementId = createAdvancementId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getId() {
|
||||
return AbstractSingleInputRecipeBuilder.this.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecipeSerializer<R> getType() {
|
||||
return getSerializer();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public JsonObject serializeAdvancement() {
|
||||
return advancement.serializeToJson();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public ResourceLocation getAdvancementId() {
|
||||
return advancementId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeRecipeData(JsonObject root) {
|
||||
AbstractSingleInputRecipeBuilder.this.serializeRecipeData(root);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package org.betterx.bclib.recipes;
|
||||
|
||||
import net.minecraft.advancements.CriterionTriggerInstance;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.level.ItemLike;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public abstract class AbstractUnlockableRecipeBuilder<T extends AbstractUnlockableRecipeBuilder> extends AbstractSimpleRecipeBuilder<T> {
|
||||
|
||||
protected AbstractUnlockableRecipeBuilder(ResourceLocation id, ItemLike output) {
|
||||
super(id, output);
|
||||
}
|
||||
|
||||
protected final Map<String, CriterionTriggerInstance> unlocks = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public T unlockedBy(ItemLike item) {
|
||||
return super.unlockedBy(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T unlockedBy(TagKey<Item> tag) {
|
||||
return super.unlockedBy(tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected T unlocks(String name, CriterionTriggerInstance trigger) {
|
||||
this.unlocks.put(name, trigger);
|
||||
return (T) this;
|
||||
}
|
||||
}
|
|
@ -1,14 +1,13 @@
|
|||
package org.betterx.bclib.recipes;
|
||||
|
||||
import org.betterx.bclib.BCLib;
|
||||
import org.betterx.bclib.config.PathConfig;
|
||||
import org.betterx.bclib.interfaces.AlloyingRecipeWorkstation;
|
||||
import org.betterx.bclib.interfaces.UnknownReceipBookCategory;
|
||||
import org.betterx.bclib.util.ItemUtil;
|
||||
import org.betterx.bclib.util.RecipeHelper;
|
||||
|
||||
import net.minecraft.core.NonNullList;
|
||||
import net.minecraft.core.RegistryAccess;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.TagKey;
|
||||
|
@ -130,77 +129,29 @@ public class AlloyingRecipe implements Recipe<Container>, UnknownReceipBookCateg
|
|||
return AlloyingRecipeWorkstation.getWorkstationIcon();
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private final static Builder INSTANCE = new Builder();
|
||||
private static boolean exist;
|
||||
public static class Builder extends AbstractDoubleInputRecipeBuilder<Builder, AlloyingRecipe> {
|
||||
private Builder(ResourceLocation id, ItemLike output) {
|
||||
super(id, output);
|
||||
this.experience = 0.0F;
|
||||
this.smeltTime = 350;
|
||||
}
|
||||
|
||||
static Builder create(ResourceLocation id, ItemLike output) {
|
||||
INSTANCE.id = id;
|
||||
INSTANCE.group = String.format("%s_%s", GROUP, id);
|
||||
INSTANCE.primaryInput = null;
|
||||
INSTANCE.secondaryInput = null;
|
||||
INSTANCE.output = output;
|
||||
INSTANCE.experience = 0.0F;
|
||||
INSTANCE.smeltTime = 350;
|
||||
INSTANCE.count = 1;
|
||||
INSTANCE.alright = RecipeHelper.exists(output);
|
||||
exist = true;
|
||||
|
||||
return INSTANCE;
|
||||
return new Builder(id, output);
|
||||
}
|
||||
|
||||
private int count = 1;
|
||||
private ResourceLocation id;
|
||||
private Ingredient primaryInput;
|
||||
private Ingredient secondaryInput;
|
||||
private ItemLike output;
|
||||
private String group;
|
||||
private float experience;
|
||||
private int smeltTime;
|
||||
private boolean alright = true;
|
||||
|
||||
protected Builder() {
|
||||
}
|
||||
|
||||
public Builder checkConfig(PathConfig config) {
|
||||
exist &= config.getBoolean("alloying", id.getPath(), true);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setGroup(String group) {
|
||||
this.group = group;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder setOutputCount(int count) {
|
||||
this.count = count;
|
||||
return this;
|
||||
return super.setOutputCount(count);
|
||||
}
|
||||
|
||||
public Builder setPrimaryInput(ItemLike... inputs) {
|
||||
for (ItemLike item : inputs) {
|
||||
this.alright &= RecipeHelper.exists(item);
|
||||
}
|
||||
this.primaryInput = Ingredient.of(inputs);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setSecondaryInput(ItemLike... inputs) {
|
||||
for (ItemLike item : inputs) {
|
||||
this.alright &= RecipeHelper.exists(item);
|
||||
}
|
||||
this.secondaryInput = Ingredient.of(inputs);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setPrimaryInput(TagKey<Item> input) {
|
||||
this.primaryInput = Ingredient.of(input);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setSecondaryInput(TagKey<Item> input) {
|
||||
this.secondaryInput = Ingredient.of(input);
|
||||
return this;
|
||||
@Override
|
||||
public Builder setOutputTag(CompoundTag tag) {
|
||||
return super.setOutputTag(tag);
|
||||
}
|
||||
|
||||
public Builder setInput(ItemLike primaryInput, ItemLike secondaryInput) {
|
||||
|
@ -225,46 +176,34 @@ public class AlloyingRecipe implements Recipe<Container>, UnknownReceipBookCateg
|
|||
return this;
|
||||
}
|
||||
|
||||
public void build() {
|
||||
if (exist) {
|
||||
if (primaryInput == null) {
|
||||
BCLib.LOGGER.warning(
|
||||
"Primary input for Alloying recipe can't be 'null', recipe {} will be ignored!",
|
||||
id
|
||||
);
|
||||
return;
|
||||
@Override
|
||||
public Builder setGroup(String group) {
|
||||
return super.setGroup(group);
|
||||
}
|
||||
if (secondaryInput == null) {
|
||||
BCLib.LOGGER.warning(
|
||||
"Secondary input for Alloying can't be 'null', recipe {} will be ignored!",
|
||||
id
|
||||
);
|
||||
return;
|
||||
|
||||
@Override
|
||||
protected boolean checkRecipe() {
|
||||
if (smeltTime < 0) {
|
||||
BCLib.LOGGER.warning("Semelt-time for recipe {} most be positive!", id);
|
||||
return false;
|
||||
}
|
||||
if (output == null) {
|
||||
BCLib.LOGGER.warning("Output for Alloying can't be 'null', recipe {} will be ignored!", id);
|
||||
return;
|
||||
return super.checkRecipe();
|
||||
}
|
||||
if (BCLRecipeManager.getRecipe(TYPE, id) != null) {
|
||||
BCLib.LOGGER.warning("Can't add Alloying recipe! Id {} already exists!", id);
|
||||
return;
|
||||
|
||||
@Override
|
||||
protected RecipeSerializer<AlloyingRecipe> getSerializer() {
|
||||
return SERIALIZER;
|
||||
}
|
||||
if (!alright) {
|
||||
BCLib.LOGGER.debug("Can't add Alloying recipe {}! Ingeredient or output not exists.", id);
|
||||
return;
|
||||
|
||||
@Override
|
||||
protected void serializeRecipeData(JsonObject root) {
|
||||
super.serializeRecipeData(root);
|
||||
|
||||
if (experience != 0) {
|
||||
root.addProperty("experience", experience);
|
||||
}
|
||||
BCLRecipeManager.addRecipe(
|
||||
TYPE,
|
||||
new AlloyingRecipe(
|
||||
id,
|
||||
group,
|
||||
primaryInput,
|
||||
secondaryInput,
|
||||
new ItemStack(output, count),
|
||||
experience,
|
||||
smeltTime
|
||||
)
|
||||
);
|
||||
if (experience != 350) {
|
||||
root.addProperty("smelttime", smeltTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -275,9 +214,11 @@ public class AlloyingRecipe implements Recipe<Container>, UnknownReceipBookCateg
|
|||
JsonArray ingredients = GsonHelper.getAsJsonArray(json, "ingredients");
|
||||
Ingredient primaryInput = Ingredient.fromJson(ingredients.get(0));
|
||||
Ingredient secondaryInput = Ingredient.fromJson(ingredients.get(1));
|
||||
|
||||
String group = GsonHelper.getAsString(json, "group", "");
|
||||
|
||||
JsonObject result = GsonHelper.getAsJsonObject(json, "result");
|
||||
ItemStack output = ItemUtil.fromJsonRecipe(result);
|
||||
ItemStack output = ItemUtil.fromJsonRecipeWithNBT(result);
|
||||
if (output == null) {
|
||||
throw new IllegalStateException("Output item does not exists!");
|
||||
}
|
||||
|
|
|
@ -1,14 +1,11 @@
|
|||
package org.betterx.bclib.recipes;
|
||||
|
||||
import org.betterx.bclib.BCLib;
|
||||
import org.betterx.bclib.config.PathConfig;
|
||||
import org.betterx.bclib.interfaces.UnknownReceipBookCategory;
|
||||
import org.betterx.bclib.util.ItemUtil;
|
||||
import org.betterx.bclib.util.RecipeHelper;
|
||||
import org.betterx.worlds.together.tag.v3.CommonItemTags;
|
||||
import org.betterx.worlds.together.world.event.WorldBootstrap;
|
||||
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.NonNullList;
|
||||
|
@ -16,7 +13,6 @@ import net.minecraft.core.Registry;
|
|||
import net.minecraft.core.RegistryAccess;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.TagParser;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.TagKey;
|
||||
|
@ -83,17 +79,7 @@ public class AnvilRecipe implements Recipe<Container>, UnknownReceipBookCategory
|
|||
}
|
||||
|
||||
static Builder create(ResourceLocation id, ItemLike output) {
|
||||
Builder.INSTANCE.id = id;
|
||||
Builder.INSTANCE.input = null;
|
||||
Builder.INSTANCE.output = output;
|
||||
Builder.INSTANCE.inputCount = 1;
|
||||
Builder.INSTANCE.toolLevel = 1;
|
||||
Builder.INSTANCE.anvilLevel = 1;
|
||||
Builder.INSTANCE.damage = 1;
|
||||
Builder.INSTANCE.alright = true;
|
||||
Builder.INSTANCE.exist = RecipeHelper.exists(output);
|
||||
|
||||
return Builder.INSTANCE;
|
||||
return new Builder(id, output);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -261,36 +247,54 @@ public class AnvilRecipe implements Recipe<Container>, UnknownReceipBookCategory
|
|||
return "AnvilRecipe [" + id + "]";
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private final static Builder INSTANCE = new Builder();
|
||||
public static class Builder extends AbstractDoubleInputRecipeBuilder<Builder, AnvilRecipe> {
|
||||
private int inputCount;
|
||||
private int toolLevel;
|
||||
private int anvilLevel;
|
||||
private int damage;
|
||||
|
||||
private ResourceLocation id;
|
||||
private Ingredient input;
|
||||
private ItemLike output;
|
||||
private int inputCount = 1;
|
||||
private int outputCount = 1;
|
||||
private int toolLevel = 1;
|
||||
private int anvilLevel = 1;
|
||||
private int damage = 1;
|
||||
private boolean alright;
|
||||
private boolean exist;
|
||||
protected Builder(ResourceLocation id, ItemLike output) {
|
||||
super(id, output);
|
||||
|
||||
private Builder() {
|
||||
this.inputCount = 1;
|
||||
this.toolLevel = 1;
|
||||
this.anvilLevel = 1;
|
||||
this.damage = 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Builder setOutputTag(CompoundTag tag) {
|
||||
return super.setOutputTag(tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Builder setOutputCount(int count) {
|
||||
return super.setOutputCount(count);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param inputItems
|
||||
* @return
|
||||
* @deprecated Use {@link #setPrimaryInput(ItemLike...)} instead
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public Builder setInput(ItemLike... inputItems) {
|
||||
this.alright &= RecipeHelper.exists(inputItems);
|
||||
this.setInput(Ingredient.of(inputItems));
|
||||
return this;
|
||||
return super.setPrimaryInput(inputItems);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param inputTag
|
||||
* @return
|
||||
* @deprecated Use {@link #setPrimaryInput(TagKey)} instead
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public Builder setInput(TagKey<Item> inputTag) {
|
||||
this.setInput(Ingredient.of(inputTag));
|
||||
return this;
|
||||
return super.setPrimaryInput(inputTag);
|
||||
}
|
||||
|
||||
@Deprecated(forRemoval = true)
|
||||
public Builder setInput(Ingredient ingredient) {
|
||||
this.input = ingredient;
|
||||
this.primaryInput = ingredient;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -299,10 +303,6 @@ public class AnvilRecipe implements Recipe<Container>, UnknownReceipBookCategory
|
|||
return this;
|
||||
}
|
||||
|
||||
public Builder setOutputCount(int count) {
|
||||
this.outputCount = count;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setToolLevel(int level) {
|
||||
this.toolLevel = level;
|
||||
|
@ -319,44 +319,39 @@ public class AnvilRecipe implements Recipe<Container>, UnknownReceipBookCategory
|
|||
return this;
|
||||
}
|
||||
|
||||
public Builder checkConfig(PathConfig config) {
|
||||
exist &= config.getBoolean("anvil", id.getPath(), true);
|
||||
return this;
|
||||
@Override
|
||||
protected RecipeSerializer<AnvilRecipe> getSerializer() {
|
||||
return SERIALIZER;
|
||||
}
|
||||
|
||||
public void build() {
|
||||
if (!exist) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (input == null) {
|
||||
BCLib.LOGGER.warning("Input for Anvil recipe can't be 'null', recipe {} will be ignored!", id);
|
||||
return;
|
||||
}
|
||||
if (output == null) {
|
||||
BCLib.LOGGER.warning("Output for Anvil recipe can't be 'null', recipe {} will be ignored!", id);
|
||||
return;
|
||||
}
|
||||
if (BCLRecipeManager.getRecipe(TYPE, id) != null) {
|
||||
BCLib.LOGGER.warning("Can't add Anvil recipe! Id {} already exists!", id);
|
||||
return;
|
||||
}
|
||||
if (!alright) {
|
||||
BCLib.LOGGER.debug("Can't add Anvil recipe {}! Ingeredient or output not exists.", id);
|
||||
return;
|
||||
}
|
||||
BCLRecipeManager.addRecipe(
|
||||
TYPE,
|
||||
new AnvilRecipe(
|
||||
id,
|
||||
input,
|
||||
new ItemStack(output, outputCount),
|
||||
inputCount,
|
||||
toolLevel,
|
||||
anvilLevel,
|
||||
damage
|
||||
)
|
||||
@Override
|
||||
protected boolean checkRecipe() {
|
||||
if (inputCount <= 0) {
|
||||
BCLib.LOGGER.warning(
|
||||
"Number of input items for Recipe must be positive. Recipe {} will be ignored!",
|
||||
id
|
||||
);
|
||||
return false;
|
||||
}
|
||||
return super.checkRecipe();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void serializeRecipeData(JsonObject root) {
|
||||
super.serializeRecipeData(root);
|
||||
|
||||
if (inputCount > 1) {
|
||||
root.addProperty("inputCount", inputCount);
|
||||
}
|
||||
if (toolLevel != 1) {
|
||||
root.addProperty("toolLevel", toolLevel);
|
||||
}
|
||||
if (anvilLevel != 1) {
|
||||
root.addProperty("anvilLevel", anvilLevel);
|
||||
}
|
||||
if (damage != 1) {
|
||||
root.addProperty("damage", damage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -365,19 +360,11 @@ public class AnvilRecipe implements Recipe<Container>, UnknownReceipBookCategory
|
|||
public AnvilRecipe fromJson(ResourceLocation id, JsonObject json) {
|
||||
Ingredient input = Ingredient.fromJson(json.get("input"));
|
||||
JsonObject result = GsonHelper.getAsJsonObject(json, "result");
|
||||
ItemStack output = ItemUtil.fromJsonRecipe(result);
|
||||
ItemStack output = ItemUtil.fromJsonRecipeWithNBT(result);
|
||||
if (output == null) {
|
||||
throw new IllegalStateException("Output item does not exists!");
|
||||
}
|
||||
if (result.has("nbt")) {
|
||||
try {
|
||||
String nbtData = GsonHelper.getAsString(result, "nbt");
|
||||
CompoundTag nbt = TagParser.parseTag(nbtData);
|
||||
output.setTag(nbt);
|
||||
} catch (CommandSyntaxException ex) {
|
||||
BCLib.LOGGER.warning("Error parse nbt data for output.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
int inputCount = GsonHelper.getAsInt(json, "inputCount", 1);
|
||||
int toolLevel = GsonHelper.getAsInt(json, "toolLevel", 1);
|
||||
int anvilLevel = GsonHelper.getAsInt(json, "anvilLevel", 1);
|
||||
|
|
|
@ -12,23 +12,23 @@ public class BCLRecipeBuilder {
|
|||
return AnvilRecipe.create(id, output);
|
||||
}
|
||||
|
||||
public static BlastFurnaceRecipe blasting(ResourceLocation id, ItemLike output) {
|
||||
return BlastFurnaceRecipe.make(id, output);
|
||||
public static CookingRecipeBuilder blasting(ResourceLocation id, ItemLike output) {
|
||||
return CookingRecipeBuilder.make(id, output).disableSmelter().enableBlastFurnace();
|
||||
}
|
||||
|
||||
public static GridRecipe crafting(ResourceLocation id, ItemLike output) {
|
||||
return GridRecipe.make(id, output);
|
||||
public static CraftingRecipeBuilder crafting(ResourceLocation id, ItemLike output) {
|
||||
return CraftingRecipeBuilder.make(id, output);
|
||||
}
|
||||
|
||||
public static FurnaceRecipe smelting(ResourceLocation id, ItemLike output) {
|
||||
return FurnaceRecipe.make(id, output);
|
||||
public static CookingRecipeBuilder smelting(ResourceLocation id, ItemLike output) {
|
||||
return CookingRecipeBuilder.make(id, output);
|
||||
}
|
||||
|
||||
public static SmithingTableRecipe smithing(ResourceLocation id, ItemLike output) {
|
||||
return SmithingTableRecipe.make(id, output);
|
||||
public static SmithingRecipeBuilder smithing(ResourceLocation id, ItemLike output) {
|
||||
return SmithingRecipeBuilder.make(id, output);
|
||||
}
|
||||
|
||||
public static StoneCutterRecipe stonecutting(ResourceLocation id, ItemLike output) {
|
||||
return StoneCutterRecipe.make(id, output);
|
||||
public static StonecutterRecipeBuilder stonecutting(ResourceLocation id, ItemLike output) {
|
||||
return StonecutterRecipeBuilder.make(id, output);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
package org.betterx.bclib.recipes;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.Container;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.BlastingRecipe;
|
||||
import net.minecraft.world.item.crafting.RecipeType;
|
||||
import net.minecraft.world.level.ItemLike;
|
||||
|
||||
public class BlastFurnaceRecipe extends CookingRecipe<BlastFurnaceRecipe, Container, BlastingRecipe> {
|
||||
BlastFurnaceRecipe(ResourceLocation id, ItemLike output) {
|
||||
super(id, RecipeType.BLASTING, output);
|
||||
}
|
||||
|
||||
static BlastFurnaceRecipe make(String modID, String name, ItemLike output) {
|
||||
return make(new ResourceLocation(modID, name), output);
|
||||
}
|
||||
|
||||
static BlastFurnaceRecipe make(ResourceLocation id, ItemLike output) {
|
||||
BlastFurnaceRecipe res = new BlastFurnaceRecipe(id, output);
|
||||
res.createAdvancement(id, false);
|
||||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BlastingRecipe buildRecipe() {
|
||||
return new BlastingRecipe(
|
||||
id,
|
||||
group,
|
||||
bookCategory,
|
||||
input,
|
||||
new ItemStack(output, count),
|
||||
experience,
|
||||
cookingTime
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
package org.betterx.bclib.recipes;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.Container;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.crafting.CookingBookCategory;
|
||||
import net.minecraft.world.item.crafting.Recipe;
|
||||
import net.minecraft.world.item.crafting.RecipeType;
|
||||
import net.minecraft.world.level.ItemLike;
|
||||
|
||||
public abstract class CookingRecipe<T extends AbstractSimpleRecipe, C extends Container, R extends Recipe<C>> extends AbstractSimpleRecipe<T, C, R> {
|
||||
protected float experience;
|
||||
protected int cookingTime;
|
||||
protected CookingBookCategory bookCategory;
|
||||
|
||||
CookingRecipe(ResourceLocation id, RecipeType<R> type, ItemLike output) {
|
||||
this(id, type, type.toString(), output);
|
||||
}
|
||||
|
||||
CookingRecipe(ResourceLocation id, RecipeType<R> type, String category, ItemLike output) {
|
||||
super(id, type, category, output);
|
||||
cookingTime = 1000;
|
||||
experience = 0;
|
||||
this.bookCategory = CookingBookCategory.MISC;
|
||||
}
|
||||
|
||||
public T setInput(ItemLike in) {
|
||||
return super.setInput(in);
|
||||
}
|
||||
|
||||
public T setInput(TagKey<Item> in) {
|
||||
return super.setInput(in);
|
||||
}
|
||||
|
||||
public T setExperience(float xp) {
|
||||
experience = xp;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T setCookingTime(int time) {
|
||||
cookingTime = time;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T setCookingBookCategory(CookingBookCategory c) {
|
||||
bookCategory = c;
|
||||
return (T) this;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,208 @@
|
|||
package org.betterx.bclib.recipes;
|
||||
|
||||
import org.betterx.bclib.BCLib;
|
||||
|
||||
import net.minecraft.data.recipes.FinishedRecipe;
|
||||
import net.minecraft.data.recipes.SimpleCookingRecipeBuilder;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.level.ItemLike;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class CookingRecipeBuilder extends AbstractUnlockableRecipeBuilder<CookingRecipeBuilder> {
|
||||
|
||||
protected float xp;
|
||||
protected int cookingTime;
|
||||
|
||||
boolean blasting, campfire, smoker, smelting;
|
||||
|
||||
static CookingRecipeBuilder make(ResourceLocation id, ItemLike output) {
|
||||
return new CookingRecipeBuilder(id, output);
|
||||
}
|
||||
|
||||
protected CookingRecipeBuilder(ResourceLocation id, ItemLike output) {
|
||||
super(id, output);
|
||||
this.xp = 0;
|
||||
this.cookingTime = 200;
|
||||
this.smelting = true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Use {@link #setPrimaryInputAndUnlock(ItemLike...)} instead
|
||||
*
|
||||
* @deprecated Use {@link #setPrimaryInputAndUnlock(ItemLike...)} instead
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public CookingRecipeBuilder setInput(ItemLike in) {
|
||||
return this.setPrimaryInputAndUnlock(in);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use {@link #setPrimaryInputAndUnlock(ItemLike...)} instead
|
||||
*
|
||||
* @param in
|
||||
* @return
|
||||
* @deprecated Use {@link #setPrimaryInputAndUnlock(ItemLike...)} instead
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public CookingRecipeBuilder setInput(TagKey<Item> in) {
|
||||
return this.setPrimaryInputAndUnlock(in);
|
||||
}
|
||||
|
||||
public CookingRecipeBuilder setExperience(float xp) {
|
||||
this.xp = xp;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CookingRecipeBuilder setCookingTime(int time) {
|
||||
this.cookingTime = time;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean checkRecipe() {
|
||||
if (smelting == false && blasting == false && campfire == false && smoker == false) {
|
||||
BCLib.LOGGER.warning(
|
||||
"No target (smelting, blasting, campfire or somer) for cooking recipe was selected. Recipe {} will be ignored!",
|
||||
id
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cookingTime < 0) {
|
||||
BCLib.LOGGER.warning(
|
||||
"cooking time must be positive. Recipe {} will be ignored!",
|
||||
id
|
||||
);
|
||||
return false;
|
||||
}
|
||||
return super.checkRecipe();
|
||||
}
|
||||
|
||||
public CookingRecipeBuilder enableSmelter() {
|
||||
this.smelting = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CookingRecipeBuilder disableSmelter() {
|
||||
this.smelting = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CookingRecipeBuilder enableBlastFurnace() {
|
||||
this.blasting = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CookingRecipeBuilder disableBlastFurnace() {
|
||||
this.blasting = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CookingRecipeBuilder enableCampfire() {
|
||||
this.campfire = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CookingRecipeBuilder disableCampfire() {
|
||||
this.campfire = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CookingRecipeBuilder enableSmoker() {
|
||||
this.smoker = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CookingRecipeBuilder disableSmoker() {
|
||||
this.smoker = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void build(boolean blasting, boolean campfire, boolean smoker) {
|
||||
this.enableSmelter();
|
||||
this.blasting = blasting;
|
||||
this.campfire = campfire;
|
||||
this.smoker = smoker;
|
||||
|
||||
build();
|
||||
}
|
||||
|
||||
public void buildWithBlasting() {
|
||||
build(true, false, false);
|
||||
}
|
||||
|
||||
public void buildFoodlike() {
|
||||
build(false, true, true);
|
||||
}
|
||||
|
||||
private void buildRecipe(Consumer<FinishedRecipe> cc, SimpleCookingRecipeBuilder builder, String postfix) {
|
||||
ResourceLocation loc = new ResourceLocation(id.getNamespace(), id.getPath() + "_" + postfix);
|
||||
for (var item : unlocks.entrySet()) {
|
||||
builder.unlockedBy(item.getKey(), item.getValue());
|
||||
}
|
||||
builder.save(cc, loc);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void buildRecipe(Consumer<FinishedRecipe> cc) {
|
||||
if (smelting) {
|
||||
buildRecipe(
|
||||
cc,
|
||||
SimpleCookingRecipeBuilder.smelting(
|
||||
primaryInput,
|
||||
category,
|
||||
output.getItem(),
|
||||
xp,
|
||||
cookingTime
|
||||
),
|
||||
"smelting"
|
||||
);
|
||||
}
|
||||
|
||||
if (blasting) {
|
||||
buildRecipe(
|
||||
cc,
|
||||
SimpleCookingRecipeBuilder.blasting(
|
||||
primaryInput,
|
||||
category,
|
||||
output.getItem(),
|
||||
xp,
|
||||
cookingTime / 2
|
||||
),
|
||||
"blasting"
|
||||
);
|
||||
}
|
||||
|
||||
if (campfire) {
|
||||
buildRecipe(
|
||||
cc,
|
||||
SimpleCookingRecipeBuilder.campfireCooking(
|
||||
primaryInput,
|
||||
category,
|
||||
output.getItem(),
|
||||
xp,
|
||||
cookingTime * 3
|
||||
),
|
||||
"campfire"
|
||||
);
|
||||
}
|
||||
|
||||
if (smoker) {
|
||||
buildRecipe(
|
||||
cc,
|
||||
SimpleCookingRecipeBuilder.campfireCooking(
|
||||
primaryInput,
|
||||
category,
|
||||
output.getItem(),
|
||||
xp,
|
||||
cookingTime / 2
|
||||
),
|
||||
"smoker"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,225 @@
|
|||
package org.betterx.bclib.recipes;
|
||||
|
||||
import org.betterx.bclib.BCLib;
|
||||
import org.betterx.bclib.config.PathConfig;
|
||||
|
||||
import net.minecraft.advancements.CriterionTriggerInstance;
|
||||
import net.minecraft.data.recipes.FinishedRecipe;
|
||||
import net.minecraft.data.recipes.ShapedRecipeBuilder;
|
||||
import net.minecraft.data.recipes.ShapelessRecipeBuilder;
|
||||
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.crafting.Ingredient;
|
||||
import net.minecraft.world.level.ItemLike;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class CraftingRecipeBuilder extends AbstractBaseRecipeBuilder<CraftingRecipeBuilder> {
|
||||
private String[] shape;
|
||||
private boolean showNotification;
|
||||
|
||||
protected CraftingRecipeBuilder(
|
||||
ResourceLocation id,
|
||||
ItemLike output
|
||||
) {
|
||||
super(id, output);
|
||||
this.showNotification = true;
|
||||
this.shape = new String[]{"#"};
|
||||
}
|
||||
|
||||
static CraftingRecipeBuilder make(ResourceLocation id, ItemLike output) {
|
||||
return new CraftingRecipeBuilder(id, output);
|
||||
}
|
||||
|
||||
protected final Map<String, CriterionTriggerInstance> unlocks = new HashMap<>();
|
||||
protected final Map<Character, Ingredient> materials = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public CraftingRecipeBuilder setOutputCount(int count) {
|
||||
return super.setOutputCount(count);
|
||||
}
|
||||
|
||||
public CraftingRecipeBuilder addMaterial(char key, TagKey<Item> value) {
|
||||
unlockedBy(value);
|
||||
materials.put(key, Ingredient.of(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
public CraftingRecipeBuilder addMaterial(char key, ItemStack... values) {
|
||||
unlockedBy(values);
|
||||
return addMaterial(key, Ingredient.of(Arrays.stream(values)));
|
||||
}
|
||||
|
||||
public CraftingRecipeBuilder addMaterial(char key, ItemLike... values) {
|
||||
for (ItemLike item : values) {
|
||||
this.alright &= BCLRecipeManager.exists(item);
|
||||
}
|
||||
unlockedBy(values);
|
||||
return addMaterial(key, Ingredient.of(values));
|
||||
}
|
||||
|
||||
private CraftingRecipeBuilder addMaterial(char key, Ingredient value) {
|
||||
materials.put(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public CraftingRecipeBuilder setShape(String... shape) {
|
||||
this.shape = shape;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CraftingRecipeBuilder shapeless() {
|
||||
this.shape = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param shape
|
||||
* @return
|
||||
* @deprecated Use {@link #shapeless()} instead
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public CraftingRecipeBuilder setList(String shape) {
|
||||
return shapeless();
|
||||
}
|
||||
|
||||
public CraftingRecipeBuilder showNotification(boolean showNotification) {
|
||||
this.showNotification = showNotification;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public CraftingRecipeBuilder unlockedBy(ItemLike item) {
|
||||
return super.unlockedBy(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CraftingRecipeBuilder unlockedBy(TagKey<Item> tag) {
|
||||
return super.unlockedBy(tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CraftingRecipeBuilder unlockedBy(ItemLike... items) {
|
||||
return super.unlockedBy(items);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CraftingRecipeBuilder unlockedBy(ItemStack... stacks) {
|
||||
return super.unlockedBy(stacks);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CraftingRecipeBuilder unlocks(String name, CriterionTriggerInstance trigger) {
|
||||
this.unlocks.put(name, trigger);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CraftingRecipeBuilder setGroup(String group) {
|
||||
return super.setGroup(group);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected boolean checkRecipe() {
|
||||
if (shape != null) return checkShaped();
|
||||
else return checkShapeless();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void buildRecipe(Consumer<FinishedRecipe> cc) {
|
||||
if (shape != null) buildShaped(cc);
|
||||
else buildShapeless(cc);
|
||||
}
|
||||
|
||||
protected boolean checkShapeless() {
|
||||
if (materials.size() == 0) {
|
||||
BCLib.LOGGER.warning("Recipe {} does not contain a material!", id);
|
||||
return false;
|
||||
}
|
||||
return super.checkRecipe();
|
||||
}
|
||||
|
||||
protected void buildShapeless(Consumer<FinishedRecipe> cc) {
|
||||
final ShapelessRecipeBuilder builder = ShapelessRecipeBuilder.shapeless(
|
||||
category, output.getItem(), output.getCount()
|
||||
);
|
||||
for (Map.Entry<String, CriterionTriggerInstance> item : unlocks.entrySet()) {
|
||||
builder.unlockedBy(item.getKey(), item.getValue());
|
||||
}
|
||||
for (Map.Entry<Character, Ingredient> mat : materials.entrySet()) {
|
||||
builder.requires(mat.getValue());
|
||||
}
|
||||
|
||||
builder.group(group);
|
||||
builder.save(cc, id);
|
||||
}
|
||||
|
||||
protected boolean checkShaped() {
|
||||
if (shape == null || shape.length == 0) {
|
||||
BCLib.LOGGER.warning("Recipe {} does not contain a shape!", id);
|
||||
return false;
|
||||
}
|
||||
if (shape.length > 3) {
|
||||
BCLib.LOGGER.warning("Recipe {} shape contains more than three lines!", id);
|
||||
return false;
|
||||
}
|
||||
int width = shape[0].length();
|
||||
if (width > 3) {
|
||||
BCLib.LOGGER.warning("Recipe {} shape is wider than three!", id);
|
||||
return false;
|
||||
}
|
||||
String allLines = "";
|
||||
for (int i = 0; i < shape.length; i++) {
|
||||
if (shape[i].length() != width) {
|
||||
BCLib.LOGGER.warning("All lines in the shape of Recipe {} should be the same length!", id);
|
||||
return false;
|
||||
}
|
||||
allLines += shape[i];
|
||||
}
|
||||
allLines = allLines.replaceAll(" ", "");
|
||||
if (allLines.length() == 1) {
|
||||
BCLib.LOGGER.warning("Recipe {} only takes in a single item and should be shapeless", id);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < allLines.length(); i++) {
|
||||
char c = allLines.charAt(i);
|
||||
if (!materials.containsKey(c)) {
|
||||
BCLib.LOGGER.warning("Recipe {} is missing the material definition for '" + c + "'!", id);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return super.checkRecipe();
|
||||
}
|
||||
|
||||
|
||||
protected void buildShaped(Consumer<FinishedRecipe> cc) {
|
||||
final ShapedRecipeBuilder builder = ShapedRecipeBuilder.shaped(
|
||||
category, output.getItem(), output.getCount()
|
||||
);
|
||||
for (Map.Entry<String, CriterionTriggerInstance> item : unlocks.entrySet()) {
|
||||
builder.unlockedBy(item.getKey(), item.getValue());
|
||||
}
|
||||
for (Map.Entry<Character, Ingredient> mat : materials.entrySet()) {
|
||||
builder.define(mat.getKey(), mat.getValue());
|
||||
}
|
||||
for (String row : shape) {
|
||||
builder.pattern(row);
|
||||
}
|
||||
builder.group(group);
|
||||
|
||||
builder.save(cc, id);
|
||||
}
|
||||
|
||||
public CraftingRecipeBuilder checkConfig(PathConfig config) {
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -1,157 +0,0 @@
|
|||
package org.betterx.bclib.recipes;
|
||||
|
||||
import org.betterx.bclib.config.PathConfig;
|
||||
|
||||
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.crafting.*;
|
||||
import net.minecraft.world.level.ItemLike;
|
||||
|
||||
public class FurnaceRecipe extends AbstractAdvancementRecipe {
|
||||
private static final FurnaceRecipe INSTANCE = new FurnaceRecipe();
|
||||
|
||||
private ResourceLocation id;
|
||||
private Ingredient input;
|
||||
private ItemLike output;
|
||||
private boolean exist;
|
||||
private String group;
|
||||
private int count;
|
||||
private int time;
|
||||
private float xp;
|
||||
protected CookingBookCategory bookCategory;
|
||||
|
||||
private FurnaceRecipe() {
|
||||
}
|
||||
|
||||
static FurnaceRecipe make(ResourceLocation id, ItemLike output) {
|
||||
INSTANCE.id = id;
|
||||
INSTANCE.group = "";
|
||||
INSTANCE.input = null;
|
||||
INSTANCE.output = output;
|
||||
INSTANCE.count = 1;
|
||||
INSTANCE.time = 200;
|
||||
INSTANCE.xp = 0;
|
||||
INSTANCE.exist = BCLRecipeManager.exists(output);
|
||||
INSTANCE.createAdvancement(INSTANCE.id, false);
|
||||
INSTANCE.bookCategory = CookingBookCategory.MISC;
|
||||
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
public FurnaceRecipe setInput(ItemLike input) {
|
||||
exist &= BCLRecipeManager.exists(input);
|
||||
this.input = Ingredient.of(input);
|
||||
unlockedBy(input);
|
||||
return this;
|
||||
}
|
||||
|
||||
public FurnaceRecipe setInput(TagKey<Item> tag) {
|
||||
this.input = Ingredient.of(tag);
|
||||
unlockedBy(tag);
|
||||
return this;
|
||||
}
|
||||
|
||||
public FurnaceRecipe checkConfig(PathConfig config) {
|
||||
exist &= config.getBoolean("furnace", id.getPath(), true);
|
||||
return this;
|
||||
}
|
||||
|
||||
public FurnaceRecipe setGroup(String group) {
|
||||
this.group = group;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FurnaceRecipe setOutputCount(int count) {
|
||||
this.count = count;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FurnaceRecipe setExperience(float xp) {
|
||||
this.xp = xp;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FurnaceRecipe setCookingTime(int time) {
|
||||
this.time = time;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FurnaceRecipe setCookingBookCategory(CookingBookCategory c) {
|
||||
bookCategory = c;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void build() {
|
||||
build(false, false, false);
|
||||
}
|
||||
|
||||
public void buildWithBlasting() {
|
||||
build(true, false, false);
|
||||
}
|
||||
|
||||
public void buildFoodlike() {
|
||||
build(false, true, true);
|
||||
}
|
||||
|
||||
public void build(boolean blasting, boolean campfire, boolean smoker) {
|
||||
if (!exist) {
|
||||
return;
|
||||
}
|
||||
|
||||
SmeltingRecipe recipe = new SmeltingRecipe(
|
||||
new ResourceLocation(id + "_smelting"),
|
||||
group,
|
||||
bookCategory,
|
||||
input,
|
||||
new ItemStack(output, count),
|
||||
xp,
|
||||
time
|
||||
);
|
||||
BCLRecipeManager.addRecipe(RecipeType.SMELTING, recipe);
|
||||
registerAdvancement(recipe, output);
|
||||
|
||||
if (blasting) {
|
||||
BlastingRecipe recipe2 = new BlastingRecipe(
|
||||
new ResourceLocation(id + "_blasting"),
|
||||
group,
|
||||
bookCategory,
|
||||
input,
|
||||
new ItemStack(output, count),
|
||||
xp,
|
||||
time / 2
|
||||
);
|
||||
|
||||
BCLRecipeManager.addRecipe(RecipeType.BLASTING, recipe2);
|
||||
}
|
||||
|
||||
if (campfire) {
|
||||
CampfireCookingRecipe recipe2 = new CampfireCookingRecipe(
|
||||
new ResourceLocation(id + "_campfire"),
|
||||
group,
|
||||
bookCategory,
|
||||
input,
|
||||
new ItemStack(output, count),
|
||||
xp,
|
||||
time * 3
|
||||
);
|
||||
|
||||
BCLRecipeManager.addRecipe(RecipeType.CAMPFIRE_COOKING, recipe2);
|
||||
}
|
||||
|
||||
if (smoker) {
|
||||
SmokingRecipe recipe2 = new SmokingRecipe(
|
||||
new ResourceLocation(id + "_smoker"),
|
||||
group,
|
||||
bookCategory,
|
||||
input,
|
||||
new ItemStack(output, count),
|
||||
xp,
|
||||
time / 2
|
||||
);
|
||||
|
||||
BCLRecipeManager.addRecipe(RecipeType.SMOKING, recipe2);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,249 +0,0 @@
|
|||
package org.betterx.bclib.recipes;
|
||||
|
||||
import org.betterx.bclib.BCLib;
|
||||
import org.betterx.bclib.config.PathConfig;
|
||||
|
||||
import net.minecraft.core.NonNullList;
|
||||
import net.minecraft.data.recipes.*;
|
||||
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.item.crafting.CraftingRecipe;
|
||||
import net.minecraft.world.item.crafting.Ingredient;
|
||||
import net.minecraft.world.item.crafting.RecipeType;
|
||||
import net.minecraft.world.level.ItemLike;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class GridRecipe extends AbstractAdvancementRecipe {
|
||||
private static final GridRecipe INSTANCE = new GridRecipe();
|
||||
|
||||
private ResourceLocation id;
|
||||
private ItemLike output;
|
||||
|
||||
private String group;
|
||||
private RecipeType<CraftingRecipe> type;
|
||||
private boolean shaped;
|
||||
private String[] shape;
|
||||
private final Map<Character, Ingredient> materialKeys = Maps.newHashMap();
|
||||
private final Map<Character, TagKey<Item>> materialTagKeys = Maps.newHashMap();
|
||||
private int count;
|
||||
private boolean showNotification;
|
||||
private boolean exist;
|
||||
|
||||
protected RecipeCategory bookCategory;
|
||||
|
||||
private GridRecipe() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Please use {@link BCLRecipeBuilder#crafting(ResourceLocation, ItemLike)} instead
|
||||
*
|
||||
* @param id
|
||||
* @param output
|
||||
* @return
|
||||
*/
|
||||
private GridRecipe(ResourceLocation id, ItemLike output) {
|
||||
this.id = id;
|
||||
this.output = output;
|
||||
|
||||
this.group = "";
|
||||
this.type = RecipeType.CRAFTING;
|
||||
this.shaped = true;
|
||||
this.showNotification = true;
|
||||
this.shape = new String[]{"#"};
|
||||
this.materialKeys.clear();
|
||||
this.count = 1;
|
||||
this.bookCategory = RecipeCategory.MISC;
|
||||
|
||||
this.exist = output != null && BCLRecipeManager.exists(output);
|
||||
this.createAdvancement(id, output);
|
||||
}
|
||||
|
||||
static GridRecipe make(ResourceLocation id, ItemLike output) {
|
||||
return new GridRecipe(id, output);
|
||||
}
|
||||
|
||||
public GridRecipe checkConfig(PathConfig config) {
|
||||
exist &= config.getBoolean("grid", id.getPath(), true);
|
||||
return this;
|
||||
}
|
||||
|
||||
public GridRecipe setGroup(String group) {
|
||||
this.group = group;
|
||||
return this;
|
||||
}
|
||||
|
||||
public GridRecipe setShape(String... shape) {
|
||||
this.shape = shape;
|
||||
return this;
|
||||
}
|
||||
|
||||
public GridRecipe setList(String shape) {
|
||||
this.shape = new String[]{shape};
|
||||
this.shaped = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
public GridRecipe addMaterial(char key, TagKey<Item> value) {
|
||||
unlockedBy(value);
|
||||
materialTagKeys.put(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public GridRecipe addMaterial(char key, ItemStack... values) {
|
||||
unlockedBy(values);
|
||||
return addMaterial(key, Ingredient.of(Arrays.stream(values)));
|
||||
}
|
||||
|
||||
public GridRecipe addMaterial(char key, ItemLike... values) {
|
||||
for (ItemLike item : values) {
|
||||
exist &= BCLRecipeManager.exists(item);
|
||||
}
|
||||
unlockedBy(values);
|
||||
return addMaterial(key, Ingredient.of(values));
|
||||
}
|
||||
|
||||
private GridRecipe addMaterial(char key, Ingredient value) {
|
||||
materialKeys.put(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public GridRecipe setOutputCount(int count) {
|
||||
this.count = count;
|
||||
return this;
|
||||
}
|
||||
|
||||
public GridRecipe showNotification(boolean showNotification) {
|
||||
this.showNotification = showNotification;
|
||||
return this;
|
||||
}
|
||||
|
||||
private NonNullList<Ingredient> getMaterials(int width, int height) {
|
||||
NonNullList<Ingredient> materials = NonNullList.withSize(width * height, Ingredient.EMPTY);
|
||||
int pos = 0;
|
||||
boolean hasNonEmpty = false;
|
||||
for (String line : shape) {
|
||||
for (int i = 0; i < width; i++) {
|
||||
char c = line.charAt(i);
|
||||
Ingredient material = materialKeys.containsKey(c)
|
||||
? materialKeys.get(c)
|
||||
: Ingredient.of(materialTagKeys.get(c));
|
||||
if (material != null && !material.isEmpty()) hasNonEmpty = true;
|
||||
materials.set(pos++, material == null ? Ingredient.EMPTY : material);
|
||||
}
|
||||
}
|
||||
if (!hasNonEmpty) return null;
|
||||
return materials;
|
||||
}
|
||||
|
||||
public GridRecipe setCategory(RecipeCategory c) {
|
||||
bookCategory = c;
|
||||
return this;
|
||||
}
|
||||
|
||||
private static List<GridRecipe> RECIPES;
|
||||
|
||||
public GridRecipe build() {
|
||||
if (RECIPES == null) RECIPES = new ArrayList<>();
|
||||
RECIPES.add(this);
|
||||
return this;
|
||||
}
|
||||
|
||||
public static void registerRecipes(Consumer<FinishedRecipe> cc) {
|
||||
if (RECIPES == null) return;
|
||||
|
||||
for (var r : RECIPES) {
|
||||
r.build(cc);
|
||||
}
|
||||
RECIPES.clear();
|
||||
}
|
||||
|
||||
public void build(Consumer<FinishedRecipe> cc) {
|
||||
if (!exist) {
|
||||
BCLib.LOGGER.warning("Unable to build Recipe " + id);
|
||||
return;
|
||||
}
|
||||
|
||||
int height = shape.length;
|
||||
int width = shape[0].length();
|
||||
ItemStack result = new ItemStack(output, count);
|
||||
if (result.is(Items.AIR)) {
|
||||
BCLib.LOGGER.warning("Unable to build Recipe " + id + ": Result is AIR");
|
||||
return;
|
||||
}
|
||||
|
||||
NonNullList<Ingredient> materials = this.getMaterials(width, height);
|
||||
if (materials == null || materials.isEmpty()) {
|
||||
BCLib.LOGGER.warning("Unable to build Recipe " + id + ": Empty Material List");
|
||||
return;
|
||||
}
|
||||
|
||||
if (shaped) {
|
||||
final ShapedRecipeBuilder builder = ShapedRecipeBuilder
|
||||
.shaped(bookCategory, output, count)
|
||||
.group(group)
|
||||
.showNotification(showNotification);
|
||||
|
||||
for (String row : this.shape) {
|
||||
builder.pattern(row);
|
||||
}
|
||||
|
||||
for (Map.Entry<Character, Ingredient> in : materialKeys.entrySet()) {
|
||||
Arrays
|
||||
.stream(in.getValue().getItems())
|
||||
.filter(i -> i.getCount() > 0)
|
||||
.forEach(stack -> builder.unlockedBy(
|
||||
"has_" + stack.getDescriptionId(),
|
||||
RecipeProvider.has(stack.getItem())
|
||||
));
|
||||
|
||||
builder.define(in.getKey(), in.getValue());
|
||||
}
|
||||
|
||||
for (Map.Entry<Character, TagKey<Item>> in : materialTagKeys.entrySet()) {
|
||||
builder.unlockedBy(
|
||||
"has_tag_" + in.getValue().location().getNamespace() + "_" + in.getValue().location().getPath(),
|
||||
RecipeProvider.has(in.getValue())
|
||||
);
|
||||
|
||||
builder.define(in.getKey(), in.getValue());
|
||||
}
|
||||
builder.save(cc, id);
|
||||
} else {
|
||||
final ShapelessRecipeBuilder builder = ShapelessRecipeBuilder
|
||||
.shapeless(bookCategory, output, count)
|
||||
.group(group);
|
||||
|
||||
for (Map.Entry<Character, Ingredient> in : materialKeys.entrySet()) {
|
||||
Arrays
|
||||
.stream(in.getValue().getItems())
|
||||
.filter(i -> i.getCount() > 0)
|
||||
.forEach(stack -> builder.unlockedBy(
|
||||
"has_" + stack.getDescriptionId(),
|
||||
RecipeProvider.has(stack.getItem())
|
||||
));
|
||||
|
||||
builder.requires(in.getValue());
|
||||
}
|
||||
|
||||
for (Map.Entry<Character, TagKey<Item>> in : materialTagKeys.entrySet()) {
|
||||
builder.unlockedBy(
|
||||
"has_tag_" + in.getValue().location().getNamespace() + "_" + in.getValue().location().getPath(),
|
||||
RecipeProvider.has(in.getValue())
|
||||
);
|
||||
|
||||
builder.requires(in.getValue());
|
||||
}
|
||||
builder.save(cc, id);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
package org.betterx.bclib.recipes;
|
||||
|
||||
import org.betterx.bclib.BCLib;
|
||||
|
||||
import net.minecraft.data.recipes.FinishedRecipe;
|
||||
import net.minecraft.data.recipes.SmithingTransformRecipeBuilder;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.crafting.Ingredient;
|
||||
import net.minecraft.world.level.ItemLike;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class SmithingRecipeBuilder extends AbstractUnlockableRecipeBuilder<SmithingRecipeBuilder> {
|
||||
protected Ingredient addon;
|
||||
|
||||
protected SmithingRecipeBuilder(
|
||||
ResourceLocation id,
|
||||
ItemLike output
|
||||
) {
|
||||
super(id, output);
|
||||
}
|
||||
|
||||
static SmithingRecipeBuilder make(ResourceLocation id, ItemLike output) {
|
||||
return new SmithingRecipeBuilder(id, output);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param in
|
||||
* @return
|
||||
* @deprecated Use {@link #setPrimaryInputAndUnlock(ItemLike...)} instead
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public SmithingRecipeBuilder setBase(ItemLike in) {
|
||||
return super.setPrimaryInputAndUnlock(in);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param in
|
||||
* @return
|
||||
* @deprecated use {@link #setPrimaryInputAndUnlock(TagKey)} instead
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public SmithingRecipeBuilder setBase(TagKey<Item> in) {
|
||||
return super.setPrimaryInputAndUnlock(in);
|
||||
}
|
||||
|
||||
public SmithingRecipeBuilder setAddition(ItemLike item) {
|
||||
this.addon = Ingredient.of(item);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected boolean checkRecipe() {
|
||||
if (addon == null || addon.isEmpty()) {
|
||||
BCLib.LOGGER.warning(
|
||||
"Addon for Recipe can't be 'null', recipe {} will be ignored!",
|
||||
id
|
||||
);
|
||||
return false;
|
||||
}
|
||||
return super.checkRecipe();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void buildRecipe(Consumer<FinishedRecipe> cc) {
|
||||
final SmithingTransformRecipeBuilder builder = SmithingTransformRecipeBuilder.smithing(
|
||||
Ingredient.EMPTY, primaryInput, addon, category, output.getItem()
|
||||
);
|
||||
for (var item : unlocks.entrySet()) {
|
||||
builder.unlocks(item.getKey(), item.getValue());
|
||||
}
|
||||
builder.save(cc, id);
|
||||
}
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
package org.betterx.bclib.recipes;
|
||||
|
||||
import org.betterx.bclib.BCLib;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.Container;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.Ingredient;
|
||||
import net.minecraft.world.item.crafting.RecipeType;
|
||||
import net.minecraft.world.item.crafting.SmithingRecipe;
|
||||
import net.minecraft.world.item.crafting.SmithingTransformRecipe;
|
||||
import net.minecraft.world.level.ItemLike;
|
||||
|
||||
public class SmithingTableRecipe extends AbstractSimpleRecipe<SmithingTableRecipe, Container, SmithingRecipe> {
|
||||
protected Ingredient addon;
|
||||
|
||||
protected SmithingTableRecipe(ResourceLocation id, ItemLike output) {
|
||||
super(id, RecipeType.SMITHING, output);
|
||||
}
|
||||
|
||||
|
||||
static SmithingTableRecipe make(ResourceLocation id, ItemLike output) {
|
||||
SmithingTableRecipe res = new SmithingTableRecipe(id, output);
|
||||
res.createAdvancement(id, false);
|
||||
return res;
|
||||
}
|
||||
|
||||
public SmithingTableRecipe setBase(ItemLike in) {
|
||||
return super.setInput(in);
|
||||
}
|
||||
|
||||
public SmithingTableRecipe setBase(TagKey<Item> in) {
|
||||
return super.setInput(in);
|
||||
}
|
||||
|
||||
public SmithingTableRecipe setAddition(ItemLike in) {
|
||||
this.exist &= BCLRecipeManager.exists(in);
|
||||
this.addon = Ingredient.of(in);
|
||||
unlockedBy(in);
|
||||
return this;
|
||||
}
|
||||
|
||||
public SmithingTableRecipe setAddition(TagKey<Item> in) {
|
||||
this.addon = Ingredient.of(in);
|
||||
unlockedBy(in);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean hasErrors() {
|
||||
if (addon == null || addon.isEmpty()) {
|
||||
BCLib.LOGGER.warning("Unable to build Recipe " + id + ": No Addon Ingredient");
|
||||
return true;
|
||||
}
|
||||
return super.hasErrors();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SmithingRecipe buildRecipe() {
|
||||
return new SmithingTransformRecipe(id, input, addon, null, new ItemStack(output, count));
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
package org.betterx.bclib.recipes;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.Container;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.RecipeType;
|
||||
import net.minecraft.world.item.crafting.StonecutterRecipe;
|
||||
import net.minecraft.world.level.ItemLike;
|
||||
|
||||
public class StoneCutterRecipe extends AbstractSimpleRecipe<StoneCutterRecipe, Container, StonecutterRecipe> {
|
||||
StoneCutterRecipe(ResourceLocation id, ItemLike output) {
|
||||
super(id, RecipeType.STONECUTTING, "stonecutting", output);
|
||||
}
|
||||
|
||||
static StoneCutterRecipe make(ResourceLocation id, ItemLike output) {
|
||||
StoneCutterRecipe res = new StoneCutterRecipe(id, output);
|
||||
res.createAdvancement(id, false);
|
||||
return res;
|
||||
}
|
||||
|
||||
public StoneCutterRecipe setInput(ItemLike in) {
|
||||
return super.setInput(in);
|
||||
}
|
||||
|
||||
public StoneCutterRecipe setInput(TagKey<Item> in) {
|
||||
return super.setInput(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected StonecutterRecipe buildRecipe() {
|
||||
return new StonecutterRecipe(id, group, input, new ItemStack(output, count));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package org.betterx.bclib.recipes;
|
||||
|
||||
import net.minecraft.data.recipes.FinishedRecipe;
|
||||
import net.minecraft.data.recipes.SingleItemRecipeBuilder;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.level.ItemLike;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class StonecutterRecipeBuilder extends AbstractUnlockableRecipeBuilder<StonecutterRecipeBuilder> {
|
||||
|
||||
protected StonecutterRecipeBuilder(
|
||||
ResourceLocation id,
|
||||
ItemLike output
|
||||
) {
|
||||
super(id, output);
|
||||
}
|
||||
|
||||
static StonecutterRecipeBuilder make(ResourceLocation id, ItemLike output) {
|
||||
return new StonecutterRecipeBuilder(id, output);
|
||||
}
|
||||
|
||||
@Override
|
||||
public StonecutterRecipeBuilder setGroup(String group) {
|
||||
return super.setGroup(group);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param in
|
||||
* @return
|
||||
* @deprecated Use {@link #setPrimaryInputAndUnlock(ItemLike...)} instead
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public StonecutterRecipeBuilder setInput(ItemLike in) {
|
||||
return super.setPrimaryInputAndUnlock(in);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param in
|
||||
* @return
|
||||
* @deprecated use {@link #setPrimaryInputAndUnlock(TagKey)} instead
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public StonecutterRecipeBuilder setInput(TagKey<Item> in) {
|
||||
return super.setPrimaryInputAndUnlock(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public StonecutterRecipeBuilder setOutputCount(int count) {
|
||||
return super.setOutputCount(count);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void buildRecipe(Consumer<FinishedRecipe> cc) {
|
||||
final SingleItemRecipeBuilder builder = SingleItemRecipeBuilder.stonecutting(
|
||||
primaryInput, category, output.getItem(), output.getCount()
|
||||
);
|
||||
for (var item : unlocks.entrySet()) {
|
||||
builder.unlockedBy(item.getKey(), item.getValue());
|
||||
}
|
||||
builder.group(group);
|
||||
builder.save(cc, id);
|
||||
}
|
||||
|
||||
}
|
|
@ -2,11 +2,16 @@ package org.betterx.bclib.util;
|
|||
|
||||
import org.betterx.bclib.BCLib;
|
||||
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.NbtUtils;
|
||||
import net.minecraft.nbt.TagParser;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.GsonHelper;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.ItemLike;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
|
@ -54,6 +59,20 @@ public class ItemUtil {
|
|||
return null;
|
||||
}
|
||||
|
||||
public static ItemStack fromJsonRecipeWithNBT(JsonObject recipe) {
|
||||
ItemStack output = ItemUtil.fromJsonRecipe(recipe);
|
||||
if (output != null && recipe.has("nbt")) {
|
||||
try {
|
||||
String nbtData = GsonHelper.getAsString(recipe, "nbt");
|
||||
CompoundTag nbt = TagParser.parseTag(nbtData);
|
||||
output.setTag(nbt);
|
||||
} catch (CommandSyntaxException ex) {
|
||||
BCLib.LOGGER.warning("Error parse nbt data for output.", ex);
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static ItemStack fromJsonRecipe(JsonObject recipe) {
|
||||
try {
|
||||
|
@ -71,4 +90,42 @@ public class ItemUtil {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public static JsonObject toJsonRecipeWithNBT(ItemStack stack) {
|
||||
return toJsonRecipeWithNBT(stack.getItem(), stack.getCount(), stack.getTag());
|
||||
}
|
||||
|
||||
public static JsonObject toJsonRecipeWithNBT(ItemLike item, int count, CompoundTag nbt) {
|
||||
JsonObject root = toJsonRecipe(item, count);
|
||||
if (nbt != null) {
|
||||
final String nbtData = NbtUtils.prettyPrint(nbt);
|
||||
root.addProperty("nbt", nbtData);
|
||||
//TODO: just for testing
|
||||
try {
|
||||
TagParser.parseTag(nbtData);
|
||||
} catch (CommandSyntaxException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
return root;
|
||||
}
|
||||
|
||||
public static JsonObject toJsonRecipe(ItemStack stack) {
|
||||
return toJsonRecipe(stack.getItem(), stack.getCount());
|
||||
}
|
||||
|
||||
public static JsonObject toJsonRecipe(ItemLike item, int count) {
|
||||
final ResourceLocation id = BuiltInRegistries.ITEM.getKey(item.asItem());
|
||||
if (id == null) {
|
||||
throw new IllegalStateException("Unknown Item " + item);
|
||||
}
|
||||
|
||||
final JsonObject root = new JsonObject();
|
||||
root.addProperty("item", BuiltInRegistries.ITEM.getKey(item.asItem()).toString());
|
||||
if (count > 1) {
|
||||
root.addProperty("count", count);
|
||||
}
|
||||
return root;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -129,4 +129,5 @@ public class JsonFactory {
|
|||
JsonElement elem = object.get(member);
|
||||
return elem == null ? def : elem.getAsString();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
package org.betterx.datagen.bclib.tests;
|
||||
|
||||
import org.betterx.bclib.BCLib;
|
||||
import org.betterx.bclib.api.v3.datagen.RecipeDataProvider;
|
||||
import org.betterx.bclib.recipes.BCLRecipeBuilder;
|
||||
import org.betterx.bclib.recipes.GridRecipe;
|
||||
import org.betterx.bclib.recipes.CraftingRecipeBuilder;
|
||||
import org.betterx.worlds.together.WorldsTogether;
|
||||
|
||||
import net.minecraft.data.recipes.FinishedRecipe;
|
||||
import net.minecraft.data.recipes.RecipeCategory;
|
||||
import net.minecraft.world.item.Items;
|
||||
|
||||
import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
|
||||
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
import java.util.List;
|
||||
|
||||
public class TestRecipes extends FabricRecipeProvider {
|
||||
public class TestRecipes extends RecipeDataProvider {
|
||||
public TestRecipes(FabricDataOutput output) {
|
||||
super(output);
|
||||
super(List.of(BCLib.MOD_ID, WorldsTogether.MOD_ID), output);
|
||||
}
|
||||
|
||||
final GridRecipe WONDER = BCLRecipeBuilder
|
||||
final CraftingRecipeBuilder WONDER = BCLRecipeBuilder
|
||||
.crafting(BCLib.makeID("test_star"), Items.NETHER_STAR)
|
||||
.setOutputCount(1)
|
||||
.setShape("ggg", "glg", "ggg")
|
||||
|
@ -27,8 +27,4 @@ public class TestRecipes extends FabricRecipeProvider {
|
|||
.setCategory(RecipeCategory.TOOLS)
|
||||
.build();
|
||||
|
||||
@Override
|
||||
public void buildRecipes(Consumer<FinishedRecipe> exporter) {
|
||||
GridRecipe.registerRecipes(exporter);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"schemaVersion": 1,
|
||||
"id": "bclib",
|
||||
"version": "2.2.5",
|
||||
"version": "2.3.0",
|
||||
"name": "BCLib",
|
||||
"description": "A library for BetterX team mods",
|
||||
"authors": [
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue