[Changes] Data driven Infusion Recipes

This commit is contained in:
Frank 2023-04-29 14:21:22 +02:00
parent a974fab707
commit 5d6e220ed4
2 changed files with 710 additions and 724 deletions

View file

@ -1,31 +1,36 @@
package org.betterx.betterend.recipe.builders; package org.betterx.betterend.recipe.builders;
import org.betterx.bclib.BCLib;
import org.betterx.bclib.interfaces.UnknownReceipBookCategory; import org.betterx.bclib.interfaces.UnknownReceipBookCategory;
import org.betterx.bclib.recipes.AbstractSingleInputRecipeBuilder;
import org.betterx.bclib.recipes.BCLRecipeManager; import org.betterx.bclib.recipes.BCLRecipeManager;
import org.betterx.bclib.util.ItemUtil; import org.betterx.bclib.util.ItemUtil;
import org.betterx.betterend.BetterEnd; import org.betterx.betterend.BetterEnd;
import org.betterx.betterend.config.Configs;
import org.betterx.betterend.rituals.InfusionRitual; import org.betterx.betterend.rituals.InfusionRitual;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.minecraft.core.NonNullList; import net.minecraft.core.NonNullList;
import net.minecraft.core.RegistryAccess; import net.minecraft.core.RegistryAccess;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.TagParser;
import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.TagKey;
import net.minecraft.util.GsonHelper; import net.minecraft.util.GsonHelper;
import net.minecraft.world.item.EnchantedBookItem;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.item.crafting.Recipe; import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.item.crafting.RecipeSerializer; import net.minecraft.world.item.crafting.RecipeSerializer;
import net.minecraft.world.item.crafting.RecipeType; import net.minecraft.world.item.crafting.RecipeType;
import net.minecraft.world.item.enchantment.Enchantment;
import net.minecraft.world.item.enchantment.EnchantmentInstance;
import net.minecraft.world.level.ItemLike; import net.minecraft.world.level.ItemLike;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.fabricmc.api.EnvType; import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment; import net.fabricmc.api.Environment;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import java.util.Arrays; import java.util.Arrays;
@ -58,6 +63,36 @@ public class InfusionRecipe implements Recipe<InfusionRitual>, UnknownReceipBook
Arrays.fill(catalysts, Ingredient.EMPTY); Arrays.fill(catalysts, Ingredient.EMPTY);
} }
public static Builder create(String id, ItemLike output) {
return create(BetterEnd.makeID(id), output);
}
public static Builder create(ResourceLocation id, ItemLike output) {
return new Builder(id, output);
}
public static Builder create(String id, ItemStack output) {
return create(BetterEnd.makeID(id), output);
}
public static Builder create(ResourceLocation id, ItemStack output) {
return new Builder(id, output);
}
public static Builder create(String id, Enchantment enchantment, int level) {
return create(BetterEnd.makeID(id), enchantment, level);
}
public static Builder create(ResourceLocation id, Enchantment enchantment, int level) {
return new Builder(id, createEnchantedBook(enchantment, level));
}
public static ItemStack createEnchantedBook(Enchantment enchantment, int level) {
ItemStack book = new ItemStack(Items.ENCHANTED_BOOK);
EnchantedBookItem.addEnchantment(book, new EnchantmentInstance(enchantment, level));
return book;
}
public int getInfusionTime() { public int getInfusionTime() {
return this.time; return this.time;
} }
@ -116,56 +151,36 @@ public class InfusionRecipe implements Recipe<InfusionRitual>, UnknownReceipBook
return TYPE; return TYPE;
} }
public static class Builder { public static class Builder extends AbstractSingleInputRecipeBuilder<Builder, InfusionRecipe> {
private final static Builder INSTANCE = new Builder(); private final Ingredient[] catalysts;
private static boolean exist; private int time;
public static Builder create(String id) { protected Builder(ResourceLocation id, ItemLike output) {
return create(BetterEnd.makeID(id)); this(id, new ItemStack(output, 1));
} }
public static Builder create(ResourceLocation id) { protected Builder(ResourceLocation id, ItemStack output) {
INSTANCE.id = id; super(id, output);
INSTANCE.input = null; this.catalysts = new Ingredient[]{
INSTANCE.output = null; Ingredient.EMPTY, Ingredient.EMPTY, Ingredient.EMPTY, Ingredient.EMPTY,
INSTANCE.time = 1; Ingredient.EMPTY, Ingredient.EMPTY, Ingredient.EMPTY, Ingredient.EMPTY
exist = Configs.RECIPE_CONFIG.getBoolean("infusion", id.getPath(), true); };
this.time = 1;
Arrays.fill(INSTANCE.catalysts, Ingredient.EMPTY);
return INSTANCE;
}
private final Ingredient[] catalysts = new Ingredient[8];
private ResourceLocation id;
private Ingredient input;
private ItemStack output;
private String group;
private int time = 1;
private Builder() {
Arrays.fill(catalysts, Ingredient.EMPTY);
} }
@Override
public Builder setGroup(String group) { public Builder setGroup(String group) {
this.group = group; return super.setGroup(group);
return this;
} }
/**
* @param input
* @return
* @deprecated use {@link #setPrimaryInput(ItemLike...)}
*/
@Deprecated(forRemoval = true)
public Builder setInput(ItemLike input) { public Builder setInput(ItemLike input) {
this.input = Ingredient.of(input); super.setPrimaryInputAndUnlock(input);
return this;
}
public Builder setOutput(ItemLike output) {
this.output = new ItemStack(output);
this.output.setCount(1);
return this;
}
public Builder setOutput(ItemStack output) {
this.output = output;
this.output.setCount(1);
return this; return this;
} }
@ -174,111 +189,122 @@ public class InfusionRecipe implements Recipe<InfusionRitual>, UnknownReceipBook
return this; return this;
} }
public Builder addCatalyst(int slot, ItemLike... items) { public Builder addCatalyst(Catalysts slot, ItemLike... items) {
if (slot > 7) return this; this.catalysts[slot.index] = Ingredient.of(items);
this.catalysts[slot] = Ingredient.of(items);
return this; return this;
} }
public void build() { public Builder addCatalyst(Catalysts slot, ItemStack stack) {
if (exist) { this.catalysts[slot.index] = Ingredient.of(stack);
if (input == null) { return this;
BetterEnd.LOGGER.warning( }
"Input for Infusion recipe can't be 'null', recipe {} will be ignored!",
public Builder addCatalyst(Catalysts slot, TagKey<Item> tag) {
this.catalysts[slot.index] = Ingredient.of(tag);
return this;
}
@Override
protected boolean checkRecipe() {
if (time < 0) {
BCLib.LOGGER.warning(
"Time should be positive, recipe {} will be ignored!",
id id
); );
return; return false;
} }
if (output == null) { return super.checkRecipe();
BetterEnd.LOGGER.warning(
"Output for Infusion recipe can't be 'null', recipe {} will be ignored!",
id
);
return;
} }
InfusionRecipe recipe = new InfusionRecipe(id, input, output);
recipe.group = group != null ? group : GROUP; @Override
recipe.time = time; protected void serializeRecipeData(JsonObject root) {
int empty = 0; super.serializeRecipeData(root);
for (int i = 0; i < catalysts.length; i++) {
if (catalysts[i].isEmpty()) empty++; if (time != 1) {
else recipe.catalysts[i] = catalysts[i]; root.addProperty("time", time);
} }
if (empty == catalysts.length) {
BetterEnd.LOGGER.warning("At least one catalyst must be non empty, recipe {} will be ignored!", id); JsonObject catalystObject = new JsonObject();
return; for (var cat : Catalysts.values()) {
if (catalysts[cat.index] != null && !catalysts[cat.index].isEmpty()) {
catalystObject.add(cat.key, ItemUtil.toJsonIngredientWithNBT(catalysts[cat.index]));
} }
BCLRecipeManager.addRecipe(TYPE, recipe);
} }
root.add("catalysts", catalystObject);
}
@Override
protected RecipeSerializer<InfusionRecipe> getSerializer() {
return SERIALIZER;
}
}
public enum Catalysts {
NORTH(0, "north"),
NORTH_EAST(1, "north_east"),
EAST(2, "east"),
SOUTH_EAST(3, ""),
SOUTH(4, "south"),
SOUTH_WEST(5, "south_west"),
WEST(6, "west"),
NORTH_WEST(7, "north_west");
public final int index;
public final String key;
Catalysts(int index, String key) {
this.index = index;
this.key = key;
} }
} }
public static class Serializer implements RecipeSerializer<InfusionRecipe> { public static class Serializer implements RecipeSerializer<InfusionRecipe> {
private Ingredient readIngredient(JsonObject obj, String key) {
if (obj.has(key)) {
JsonElement el = obj.get(key);
if (el.isJsonObject()) {
JsonObject o = el.getAsJsonObject();
//directly read as ingredient
if (o.has("tag")) {
return ItemUtil.fromJsonIngredientWithNBT(o);
} else {
return Ingredient.of(ItemUtil.fromJsonRecipeWithNBT(o));
}
} else if (el.isJsonArray()) {
//this is an Ingredient-Array, so read as such
JsonObject o = el.getAsJsonObject();
return ItemUtil.fromJsonIngredientWithNBT(o);
} else if (obj.isJsonPrimitive()) {
String s = GsonHelper.getAsString(obj, key, "");
ItemStack catalyst = ItemUtil.fromStackString(s);
return (catalyst != null && !catalyst.isEmpty())
? Ingredient.of(catalyst.getItem())
: Ingredient.EMPTY;
} else {
throw new IllegalStateException("Invalid catalyst ingredient for " + key + ": " + el.toString());
}
}
return null;
}
@Override @Override
public InfusionRecipe fromJson(ResourceLocation id, JsonObject json) { public InfusionRecipe fromJson(ResourceLocation id, JsonObject json) {
InfusionRecipe recipe = new InfusionRecipe(id); InfusionRecipe recipe = new InfusionRecipe(id);
JsonObject inputObject = GsonHelper.getAsJsonObject(json, "input"); JsonObject inputObject = GsonHelper.getAsJsonObject(json, "input");
recipe.input = Ingredient.fromJson(inputObject); recipe.input = ItemUtil.fromJsonIngredientWithNBT(inputObject);
if (inputObject.has("nbt") && !recipe.input.isEmpty()) {
try {
String nbtData = GsonHelper.getAsString(inputObject, "nbt");
CompoundTag nbt = TagParser.parseTag(nbtData);
recipe.input.getItems()[0].setTag(nbt);
} catch (CommandSyntaxException ex) {
BetterEnd.LOGGER.warning("Error parse nbt data for input.", ex);
}
}
JsonObject result = GsonHelper.getAsJsonObject(json, "result"); JsonObject result = GsonHelper.getAsJsonObject(json, "result");
recipe.output = ItemUtil.fromJsonRecipe(result); recipe.output = ItemUtil.fromJsonRecipeWithNBT(result);
if (recipe.output == null) { if (recipe.output == null) {
throw new IllegalStateException("Output item does not exists!"); throw new IllegalStateException("Output item does not exists!");
} }
if (result.has("nbt")) {
try {
String nbtData = GsonHelper.getAsString(result, "nbt");
CompoundTag nbt = TagParser.parseTag(nbtData);
recipe.output.setTag(nbt);
} catch (CommandSyntaxException ex) {
BetterEnd.LOGGER.warning("Error parse nbt data for output.", ex);
}
}
recipe.group = GsonHelper.getAsString(json, "group", GROUP); recipe.group = GsonHelper.getAsString(json, "group", GROUP);
recipe.time = GsonHelper.getAsInt(json, "time", 1); recipe.time = GsonHelper.getAsInt(json, "time", 1);
JsonObject catalysts = GsonHelper.getAsJsonObject(json, "catalysts"); JsonObject catalysts = GsonHelper.getAsJsonObject(json, "catalysts");
ItemStack catalyst = ItemUtil.fromStackString(GsonHelper.getAsString(catalysts, "north", "")); for (var cat : Catalysts.values()) {
recipe.catalysts[0] = (catalyst != null && !catalyst.isEmpty()) recipe.catalysts[cat.index] = readIngredient(catalysts, cat.key);
? Ingredient.of(catalyst.getItem()) }
: Ingredient.EMPTY;
catalyst = ItemUtil.fromStackString(GsonHelper.getAsString(catalysts, "north_east", ""));
recipe.catalysts[1] = (catalyst != null && !catalyst.isEmpty())
? Ingredient.of(catalyst.getItem())
: Ingredient.EMPTY;
catalyst = ItemUtil.fromStackString(GsonHelper.getAsString(catalysts, "east", ""));
recipe.catalysts[2] = (catalyst != null && !catalyst.isEmpty())
? Ingredient.of(catalyst.getItem())
: Ingredient.EMPTY;
catalyst = ItemUtil.fromStackString(GsonHelper.getAsString(catalysts, "south_east", ""));
recipe.catalysts[3] = (catalyst != null && !catalyst.isEmpty())
? Ingredient.of(catalyst.getItem())
: Ingredient.EMPTY;
catalyst = ItemUtil.fromStackString(GsonHelper.getAsString(catalysts, "south", ""));
recipe.catalysts[4] = (catalyst != null && !catalyst.isEmpty())
? Ingredient.of(catalyst.getItem())
: Ingredient.EMPTY;
catalyst = ItemUtil.fromStackString(GsonHelper.getAsString(catalysts, "south_west", ""));
recipe.catalysts[5] = (catalyst != null && !catalyst.isEmpty())
? Ingredient.of(catalyst.getItem())
: Ingredient.EMPTY;
catalyst = ItemUtil.fromStackString(GsonHelper.getAsString(catalysts, "west", ""));
recipe.catalysts[6] = (catalyst != null && !catalyst.isEmpty())
? Ingredient.of(catalyst.getItem())
: Ingredient.EMPTY;
catalyst = ItemUtil.fromStackString(GsonHelper.getAsString(catalysts, "north_west", ""));
recipe.catalysts[7] = (catalyst != null && !catalyst.isEmpty())
? Ingredient.of(catalyst.getItem())
: Ingredient.EMPTY;
return recipe; return recipe;
} }