package lv.enes.mc.eris_alchemy.recipe; import com.google.gson.Gson; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonSyntaxException; import jakarta.annotation.Nonnull; import lv.enes.mc.eris_alchemy.ErisAlchemyRegistry; import net.minecraft.core.RegistryAccess; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.inventory.CraftingContainer; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.CraftingBookCategory; import net.minecraft.world.item.crafting.CustomRecipe; import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.RecipeSerializer; import net.minecraft.world.level.Level; import org.quiltmc.qsl.recipe.api.serializer.QuiltRecipeSerializer; import java.util.ArrayList; import java.util.Arrays; public class CovalenceRepair extends CustomRecipe { public static class Serializer implements QuiltRecipeSerializer { private static class Json { CraftingBookCategory category = CraftingBookCategory.MISC; JsonElement dust; JsonElement materials = new JsonObject(); JsonElement tools = new JsonObject(); } @Override public JsonObject toJson(CovalenceRepair recipe) { var res = new JsonObject(); res.addProperty("category", recipe.category().toString()); res.add("dust", recipe.dust.toJson()); res.add("materials", recipe.materials.toJson()); res.add("tools", recipe.tools.toJson()); return res; } @Nonnull @Override public CovalenceRepair fromJson(ResourceLocation id, JsonObject json) { var recipeJson = new Gson().fromJson(json, Json.class); if (recipeJson.dust == null) { throw new JsonSyntaxException("A required attribute is missing"); } var dust = Ingredient.fromJson(recipeJson.dust); var materials = Ingredient.fromJson(recipeJson.materials); var tools = Ingredient.fromJson(recipeJson.tools); return new CovalenceRepair(id, recipeJson.category, dust, materials, tools); } @Override public void toNetwork(FriendlyByteBuf buf, CovalenceRepair recipe) { buf.writeEnum(recipe.category()); recipe.dust.toNetwork(buf); recipe.materials.toNetwork(buf); recipe.tools.toNetwork(buf); } @Nonnull @Override public CovalenceRepair fromNetwork(ResourceLocation id, FriendlyByteBuf buf) { var category = buf.readEnum(CraftingBookCategory.class); var dust = Ingredient.fromNetwork(buf); var materials = Ingredient.fromNetwork(buf); var tools = Ingredient.fromNetwork(buf); return new CovalenceRepair(id, category, dust, materials, tools); } } private record Inputs(ItemStack toolStack, int dustCount) {} private final static int DUSTS_TO_FIX = 8; /** What dust do we use to repair. */ private final Ingredient dust; /** What materials this dust can repair. */ private final Ingredient materials; /** What tools can this dust repair. */ private final Ingredient tools; public CovalenceRepair( ResourceLocation id, CraftingBookCategory category, Ingredient dust, Ingredient materials, Ingredient tools ) { super(id, category); this.dust = dust; this.materials = materials; this.tools = tools; } @Override public boolean canCraftInDimensions(int width, int height) { return width * height > 2; } @Override public boolean matches(CraftingContainer inventory, Level world) { return getInputs(inventory) != null; } @Nonnull @Override public ItemStack assemble(CraftingContainer inventory, RegistryAccess registryManager) { var inputs = getInputs(inventory); if (inputs == null) { return ItemStack.EMPTY; } var newToolStack = inputs.toolStack.copy(); var repairedAmount = inputs.toolStack.getItem().getMaxDamage() * inputs.dustCount / DUSTS_TO_FIX; newToolStack.setDamageValue(inputs.toolStack.getDamageValue() - repairedAmount); return newToolStack; } @Nonnull @Override public RecipeSerializer getSerializer() { return ErisAlchemyRegistry.RecipeSerializers.COVALENCE_REPAIR; } private boolean isTool(ItemStack stack) { if (!stack.isDamageableItem() || !stack.isDamaged() || stack.getCount() != 1) { return false; } if (tools.test(stack)) { return true; } var item = stack.getItem(); return Arrays.stream(materials.getItems()).anyMatch(material -> item.isValidRepairItem(stack, material)); } private boolean isDust(ItemStack stack) { return dust.test(stack); } /** @return null if recipe isn't correct. */ private Inputs getInputs(CraftingContainer inventory) { ItemStack toolStack = null; var dustStacks = new ArrayList(); for (var i = 0; i < inventory.getContainerSize(); i++) { var stack = inventory.getItem(i); if (stack.isEmpty()) { continue; } if (isDust(stack) && (dustStacks.isEmpty() || ItemStack.isSameItemSameTags(dustStacks.get(0), stack))) { dustStacks.add(stack); } else if (toolStack == null) { toolStack = stack; } else { return null; } } if (toolStack == null || dustStacks.isEmpty() || !isTool(toolStack)) { return null; } return new Inputs(toolStack, dustStacks.size()); } }