Class RecipeBuilder

java.lang.Object
dev.itsharshxd.zentrix.api.recipe.RecipeBuilder

public class RecipeBuilder extends Object
Fluent builder for creating custom Zentrix recipes.

This builder allows addon developers to create shaped or shapeless crafting recipes that integrate with the Zentrix recipe system.

IMPORTANT: Craft Limits are GLOBAL per World!

Craft limits restrict how many TOTAL times a recipe can be crafted in a world/game, not per player:

  • One-time (oneTime()): Only 1 player total can craft it per world
  • Craft limit (craftLimit(9)): Only 9 total crafts per world (any players)
  • Unlimited: Any number of players can craft unlimited times

Craft Limit Rules

  • oneTime() and craftLimit(n) are mutually exclusive
  • Setting oneTime(true) clears any previously set craft limit
  • Setting craftLimit(n) clears the one-time flag
  • Use unlimited() to remove all limits

Creating a Shaped Recipe


 RecipeBuilder builder = new RecipeBuilder()
     .id("super-sword")
     .shaped()
     .result(new ItemStack(Material.DIAMOND_SWORD))
     .pattern("DDD", "DSD", "DDD")
     .ingredient('D', new ItemStack(Material.DIAMOND))
     .ingredient('S', new ItemStack(Material.STICK))
     .craftLimit(5);  // Only 5 total crafts per world

 // Register via RecipeService
 recipeService.registerRecipe(builder);
 

Creating a Shapeless Recipe


 RecipeBuilder builder = new RecipeBuilder()
     .id("quick-diamonds")
     .shapeless()
     .result(new ItemStack(Material.DIAMOND, 4))
     .addIngredient(new ItemStack(Material.COAL, 8))
     .addIngredient(new ItemStack(Material.IRON_INGOT, 4))
     .oneTime();  // Only 1 player can craft this per world

 recipeService.registerRecipe(builder);
 
Since:
1.0.1
See Also:
  • Constructor Details

    • RecipeBuilder

      public RecipeBuilder()
      Creates a new RecipeBuilder instance.
  • Method Details

    • id

      @NotNull public @NotNull RecipeBuilder id(@NotNull @NotNull String id)
      Sets the unique identifier for this recipe.

      Recipe IDs must only contain lowercase letters, numbers, hyphens, and underscores. The ID will be automatically converted to lowercase.

      Parameters:
      id - The recipe ID (e.g., "super-sword", "magic_potion")
      Returns:
      This builder for chaining
      Throws:
      IllegalArgumentException - if the ID is null, empty, or contains invalid characters
    • result

      @NotNull public @NotNull RecipeBuilder result(@NotNull @NotNull org.bukkit.inventory.ItemStack result)
      Sets the result item that this recipe produces.
      Parameters:
      result - The result ItemStack (amount determines output quantity)
      Returns:
      This builder for chaining
      Throws:
      IllegalArgumentException - if result is null or AIR
    • shaped

      @NotNull public @NotNull RecipeBuilder shaped()
      Sets this recipe as a shaped recipe.

      Shaped recipes require ingredients to be in specific grid positions. Use pattern(String...) and ingredient(char, ItemStack) to define the crafting pattern.

      Note: Calling this clears any shapeless ingredients previously added.

      Returns:
      This builder for chaining
    • shapeless

      @NotNull public @NotNull RecipeBuilder shapeless()
      Sets this recipe as a shapeless recipe.

      Shapeless recipes allow ingredients to be placed anywhere in the grid. Use addIngredient(ItemStack) to add required ingredients.

      Note: Calling this clears any shaped pattern/ingredients previously set.

      Returns:
      This builder for chaining
    • pattern

      @NotNull public @NotNull RecipeBuilder pattern(@NotNull @NotNull String... pattern)
      Sets the crafting pattern for a shaped recipe.

      The pattern is an array of 1-3 strings, each representing a row of the crafting grid. Each character maps to an ingredient. Use a space character for empty slots.

      Example patterns:

      
       // 3x3 pattern
       .pattern("DDD", "DSD", "DDD")
      
       // 2x2 pattern (centered)
       .pattern("DD", "DD")
      
       // 1x3 pattern (stick-like)
       .pattern("D", "D", "D")
       
      Parameters:
      pattern - The pattern rows (1-3 rows, each 1-3 characters)
      Returns:
      This builder for chaining
      Throws:
      IllegalArgumentException - if pattern is invalid
    • ingredient

      @NotNull public @NotNull RecipeBuilder ingredient(char key, @NotNull @NotNull org.bukkit.inventory.ItemStack item)
      Maps a pattern character to an ingredient item.

      Each unique character in the pattern (except spaces) should be mapped to an ingredient using this method.

      Parameters:
      key - The pattern character (must not be a space)
      item - The ingredient item for this character
      Returns:
      This builder for chaining
      Throws:
      IllegalArgumentException - if item is null or key is a space
    • addIngredient

      @NotNull public @NotNull RecipeBuilder addIngredient(@NotNull @NotNull org.bukkit.inventory.ItemStack item)
      Adds an ingredient to a shapeless recipe.

      For shapeless recipes, call this method for each required ingredient. The same ingredient can be added multiple times if multiple are required.

      Parameters:
      item - The ingredient item
      Returns:
      This builder for chaining
      Throws:
      IllegalArgumentException - if item is null or AIR
    • addIngredient

      @NotNull public @NotNull RecipeBuilder addIngredient(@NotNull @NotNull org.bukkit.inventory.ItemStack item, int amount)
      Adds multiple of the same ingredient to a shapeless recipe.
      Parameters:
      item - The ingredient item
      amount - How many of this ingredient are required (1-9)
      Returns:
      This builder for chaining
      Throws:
      IllegalArgumentException - if item is null/AIR or amount is invalid
    • addIngredient

      @NotNull public @NotNull RecipeBuilder addIngredient(@NotNull @NotNull org.bukkit.Material material)
      Adds an ingredient using just a Material type.
      Parameters:
      material - The ingredient material
      Returns:
      This builder for chaining
      Throws:
      IllegalArgumentException - if material is null or AIR
    • addIngredient

      @NotNull public @NotNull RecipeBuilder addIngredient(@NotNull @NotNull org.bukkit.Material material, int amount)
      Adds multiple of a Material ingredient.
      Parameters:
      material - The ingredient material
      amount - How many of this ingredient are required (1-9)
      Returns:
      This builder for chaining
      Throws:
      IllegalArgumentException - if material is null/AIR or amount is invalid
    • oneTime

      @NotNull public @NotNull RecipeBuilder oneTime(boolean oneTime)
      Sets whether this recipe can only be crafted once per world/game.

      IMPORTANT: One-time means only 1 player TOTAL can craft this recipe per world/game, not once per player!

      Example: If one-time is enabled and Player A crafts it, Player B cannot craft it in the same game.

      Note: Setting oneTime(true) will clear any previously set craft limit, as these options are mutually exclusive.

      Parameters:
      oneTime - true to make this a one-time recipe (1 total craft per world)
      Returns:
      This builder for chaining
    • oneTime

      @NotNull public @NotNull RecipeBuilder oneTime()
      Marks this recipe as a one-time recipe.

      Equivalent to oneTime(true). Only 1 player TOTAL can craft this recipe per world/game!

      Note: This will clear any previously set craft limit, as oneTime and craftLimit are mutually exclusive.

      Returns:
      This builder for chaining
    • craftLimit

      @NotNull public @NotNull RecipeBuilder craftLimit(int limit)
      Sets the maximum number of TOTAL crafts for this recipe per world/game.

      IMPORTANT: This is a GLOBAL limit, not per player! If set to 9, only 9 total crafts by ANY players are allowed per world.

      Note: Setting a craft limit will clear the one-time flag, as these options are mutually exclusive. Use oneTime() if you want exactly 1 craft per world.

      Use -1 or unlimited() for no limit.

      Parameters:
      limit - The GLOBAL craft limit (must be -1 or positive)
      Returns:
      This builder for chaining
      Throws:
      IllegalArgumentException - if limit is less than -1 or zero
    • unlimited

      @NotNull public @NotNull RecipeBuilder unlimited()
      Removes any craft limit from this recipe.

      The recipe can be crafted unlimited times by any number of players.

      Returns:
      This builder for chaining
    • hasRestrictions

      public boolean hasRestrictions()
      Checks if this recipe has any craft restrictions.
      Returns:
      true if oneTime is enabled or craftLimit is set
    • getEffectiveLimit

      public int getEffectiveLimit()
      Gets the effective limit for this recipe.

      Returns:

      • 1 if one-time is enabled
      • The craft limit if set (and > 0)
      • -1 if unlimited

      Returns:
      The effective craft limit
    • customField

      @NotNull public @NotNull RecipeBuilder customField(@NotNull @NotNull String key, @Nullable @Nullable Object value)
      Adds a custom metadata field to this recipe.

      Custom fields can store additional information about the recipe that addons can read later. Common fields include:

      • addon_id - The addon that created this recipe
      • creator - Player name who created the recipe

      Reserved field names: one_time, craft_limit, creation_time - these are managed internally.

      Parameters:
      key - The field key (cannot be null)
      value - The field value (should be serializable, can be null to remove)
      Returns:
      This builder for chaining
      Throws:
      IllegalArgumentException - if key is a reserved field name
    • removeCustomField

      @NotNull public @NotNull RecipeBuilder removeCustomField(@NotNull @NotNull String key)
      Removes a custom metadata field from this recipe.
      Parameters:
      key - The field key to remove
      Returns:
      This builder for chaining
    • hasCustomField

      public boolean hasCustomField(@NotNull @NotNull String key)
      Checks if a custom field exists.
      Parameters:
      key - The field key
      Returns:
      true if the field exists
    • getId

      @Nullable public @Nullable String getId()
      Gets the recipe ID.
      Returns:
      The recipe ID, or null if not set
    • getResult

      @Nullable public @Nullable org.bukkit.inventory.ItemStack getResult()
      Gets the result item.
      Returns:
      The result ItemStack (cloned), or null if not set
    • getType

      @NotNull public ZentrixRecipe.RecipeType getType()
      Gets the recipe type.
      Returns:
      The recipe type (SHAPED or SHAPELESS)
    • getPattern

      @NotNull public @NotNull String[] getPattern()
      Gets the crafting pattern (for shaped recipes).
      Returns:
      A copy of the pattern array
    • getIngredientMap

      @NotNull public @NotNull Map<Character,org.bukkit.inventory.ItemStack> getIngredientMap()
      Gets the ingredient map (for shaped recipes).
      Returns:
      Map of pattern characters to ingredients (cloned)
    • getShapelessIngredients

      @NotNull public @NotNull List<org.bukkit.inventory.ItemStack> getShapelessIngredients()
      Gets the shapeless ingredients list.
      Returns:
      List of ingredients for shapeless recipes (cloned)
    • isOneTime

      public boolean isOneTime()
      Checks if this is a one-time recipe.
      Returns:
      true if one-time (1 total craft per world)
    • getCraftLimit

      public int getCraftLimit()
      Gets the craft limit.
      Returns:
      The craft limit, or -1 if unlimited
    • getCustomFields

      @NotNull public @NotNull Map<String,Object> getCustomFields()
      Gets all custom fields.
      Returns:
      Map of custom fields (copy)
    • validate

      public void validate() throws IllegalStateException
      Validates that this builder has all required fields set correctly.

      Checks performed:

      • Recipe ID is set and valid
      • Result item is set
      • Shaped recipes have a pattern with all characters mapped
      • Shapeless recipes have 1-9 ingredients

      Throws:
      IllegalStateException - if the builder is not valid
    • isValid

      public boolean isValid()
      Checks if this builder is valid without throwing an exception.
      Returns:
      true if the builder has all required fields
    • getValidationErrors

      @NotNull public @NotNull List<String> getValidationErrors()
      Gets a list of validation errors without throwing.
      Returns:
      List of error messages, empty if valid
    • copy

      @NotNull public @NotNull RecipeBuilder copy()
      Creates a copy of this builder.
      Returns:
      A new RecipeBuilder with the same configuration
    • reset

      @NotNull public @NotNull RecipeBuilder reset()
      Resets this builder to its initial state.
      Returns:
      This builder for chaining
    • toString

      public String toString()
      Overrides:
      toString in class Object