Interface ArtificialEnchantmentsAPI

All Known Implementing Classes:
ArtificialEnchantmentsAPIImpl

public interface ArtificialEnchantmentsAPI
The primary entry point for the Artificial Enchantments library.

This interface provides methods for registering custom enchantments, applying them to items, and querying enchantment state.

Registry and event bus internals are safe for concurrent access, but item mutation and effect execution should still be treated as normal server-side work. The public scheduler abstraction helps dependent plugins centralize their own scheduling decisions.

Native-First Storage Policy:
This library uses Bukkit's native ItemMeta as the source of truth for enchantment state. NBT storage is reserved for auxiliary metadata only. This design prevents state drift and ensures compatibility with vanilla enchantment handling.

Getting Started:


 // In your plugin's onEnable()
 ArtificialEnchantmentsAPI api = ArtificialEnchantmentsAPI.create(this);
 
 // Or access the shared instance after bootstrap
 ArtificialEnchantmentsAPI api = ArtificialEnchantmentsAPI.getInstance();
 
Since:
0.1.0
See Also:
  • Method Details

    • create

      @NotNull static @NotNull ArtificialEnchantmentsAPI create(@NotNull @NotNull org.bukkit.plugin.Plugin plugin)
      Creates or returns the shared API instance.

      The first caller initializes the library. Later calls return the same shared instance and do not rebind ownership to the newer plugin.

      Parameters:
      plugin - the plugin requesting the API (must not be null)
      Returns:
      the shared API instance
      Since:
      0.1.0
    • getInstance

      @NotNull static @NotNull ArtificialEnchantmentsAPI getInstance()
      Gets the shared API instance after the library has been initialized.

      Use this to access the API after the bootstrap phase is complete. This returns the same instance for all callers.

      Returns:
      the shared API instance
      Throws:
      IllegalStateException - if the API has not been initialized
      Since:
      0.1.0
    • registerBootstrapEnchantment

      static void registerBootstrapEnchantment(@NotNull @NotNull EnchantmentDefinition definition)
      Queues an enchantment definition for Paper's native registry bootstrap.

      Paper custom enchantments must be known during the registry compose lifecycle, before ordinary JavaPlugin#onEnable() methods run. Dependent plugins that need client-visible native enchantments should call this from their own PluginBootstrap#bootstrap(...) method.

      Parameters:
      definition - the enchantment definition to register natively
      Throws:
      IllegalStateException - if Paper's native registry compose window has closed
      Since:
      1.0.3
    • registerEnchantment

      @NotNull @NotNull ArtificialEnchantmentsAPI registerEnchantment(@NotNull @NotNull EnchantmentDefinition definition)
      Registers a new enchantment definition with the library.

      The enchantment becomes available for application to items immediately. On Paper 1.21+, native client visibility requires the definition to be queued during bootstrap via registerBootstrapEnchantment(EnchantmentDefinition). Calling this after Paper's registry compose event has closed fails fast because the native registry can no longer accept new enchantments.

      Thread Safety: This operation is thread-safe.

      Parameters:
      definition - the enchantment definition to register (must not be null)
      Returns:
      this API instance for chaining
      Throws:
      IllegalArgumentException - if definition is null or a duplicate key exists
      IllegalStateException - if Paper's native registry compose window has closed
      Since:
      0.1.0
    • unregisterEnchantment

      boolean unregisterEnchantment(@NotNull @NotNull org.bukkit.NamespacedKey key)
      Unregisters an enchantment by its key.

      Removes the enchantment from the registry. Items already enchanted with this enchantment retain their effects until the items are modified.

      Thread Safety: This operation is thread-safe.

      Parameters:
      key - the enchantment's namespaced key (must not be null)
      Returns:
      true if an enchantment was removed, false if not found
      Since:
      0.1.0
    • getEnchantment

      @NotNull @NotNull Optional<EnchantmentDefinition> getEnchantment(@NotNull @NotNull org.bukkit.NamespacedKey key)
      Gets an enchantment definition by its key.
      Parameters:
      key - the enchantment's namespaced key (must not be null)
      Returns:
      the definition if found, empty otherwise
      Since:
      0.1.0
    • getAllEnchantments

      @NotNull @NotNull Collection<EnchantmentDefinition> getAllEnchantments()
      Gets all registered enchantment definitions.
      Returns:
      an unmodifiable collection of all enchantments
      Since:
      0.1.0
    • getEnchantmentsFor

      @NotNull @NotNull Set<EnchantmentDefinition> getEnchantmentsFor(@NotNull org.bukkit.Material material)
      Gets all enchantments applicable to a specific material.
      Parameters:
      material - the material to check (must not be null)
      Returns:
      a set of enchantments that can be applied to this material
      Since:
      0.1.0
    • applyEnchantment

      @NotNull @NotNull org.bukkit.inventory.ItemStack applyEnchantment(@NotNull @NotNull org.bukkit.inventory.ItemStack item, @NotNull @NotNull EnchantmentDefinition enchantment, int level)
      Applies an enchantment to an item at the specified level.

      The item's ItemMeta is updated with the enchantment. The level must be within the enchantment's defined min/max bounds.

      Native-First Policy: The enchantment is stored in native ItemMeta, not duplicated in NBT.

      Parameters:
      item - the item to enchant (must not be null or air)
      enchantment - the enchantment to apply (must not be null)
      level - the level to apply (must be within bounds)
      Returns:
      the enchanted item (may be same instance)
      Throws:
      IllegalArgumentException - if parameters are invalid
      Since:
      0.1.0
    • applyEnchantment

      @NotNull @NotNull org.bukkit.inventory.ItemStack applyEnchantment(@NotNull @NotNull org.bukkit.inventory.ItemStack item, @NotNull @NotNull org.bukkit.NamespacedKey key, int level)
      Applies an enchantment by its registry key.

      Convenience method that looks up the definition before application.

      Parameters:
      item - the item to enchant (must not be null or air)
      key - the enchantment's namespaced key (must not be null)
      level - the level to apply
      Returns:
      the enchanted item
      Throws:
      IllegalArgumentException - if enchantment is not registered
      Since:
      0.1.0
    • removeEnchantment

      @NotNull @NotNull org.bukkit.inventory.ItemStack removeEnchantment(@NotNull @NotNull org.bukkit.inventory.ItemStack item, @NotNull @NotNull EnchantmentDefinition enchantment)
      Removes an enchantment from an item.
      Parameters:
      item - the item to modify (must not be null)
      enchantment - the enchantment to remove (must not be null)
      Returns:
      the modified item
      Since:
      0.1.0
    • removeEnchantment

      @NotNull @NotNull org.bukkit.inventory.ItemStack removeEnchantment(@NotNull @NotNull org.bukkit.inventory.ItemStack item, @NotNull @NotNull org.bukkit.NamespacedKey key)
      Removes an enchantment by its key.
      Parameters:
      item - the item to modify (must not be null)
      key - the enchantment's namespaced key (must not be null)
      Returns:
      the modified item
      Since:
      0.1.0
    • removeAllEnchantments

      @NotNull @NotNull org.bukkit.inventory.ItemStack removeAllEnchantments(@NotNull @NotNull org.bukkit.inventory.ItemStack item)
      Removes all artificial enchantments from an item.

      Vanilla enchantments are preserved. Only enchantments registered through this API are removed.

      Parameters:
      item - the item to clear (must not be null)
      Returns:
      the modified item
      Since:
      0.1.0
    • getEnchantmentLevel

      int getEnchantmentLevel(@NotNull @NotNull org.bukkit.inventory.ItemStack item, @NotNull @NotNull EnchantmentDefinition enchantment)
      Gets the level of an enchantment on an item.
      Parameters:
      item - the item to check (must not be null)
      enchantment - the enchantment to look for (must not be null)
      Returns:
      the enchantment level, or 0 if not present
      Since:
      0.1.0
    • getEnchantmentLevel

      int getEnchantmentLevel(@NotNull @NotNull org.bukkit.inventory.ItemStack item, @NotNull @NotNull org.bukkit.NamespacedKey key)
      Gets the level of an enchantment by its key.
      Parameters:
      item - the item to check (must not be null)
      key - the enchantment's namespaced key (must not be null)
      Returns:
      the enchantment level, or 0 if not present
      Since:
      0.1.0
    • getEnchantments

      @NotNull Map<EnchantmentDefinition,Integer> getEnchantments(@NotNull @NotNull org.bukkit.inventory.ItemStack item)
      Gets all artificial enchantments on an item.

      Returns a map of enchantment definitions to their levels. The map is unmodifiable and represents a snapshot of the item's state.

      Parameters:
      item - the item to query (must not be null)
      Returns:
      map of enchantments to levels (never null, may be empty)
      Since:
      0.1.0
    • hasEnchantment

      boolean hasEnchantment(@NotNull @NotNull org.bukkit.inventory.ItemStack item, @NotNull @NotNull EnchantmentDefinition enchantment)
      Checks if an item has a specific enchantment.
      Parameters:
      item - the item to check (must not be null)
      enchantment - the enchantment to look for (must not be null)
      Returns:
      true if the enchantment is present at any level
      Since:
      0.1.0
    • hasEnchantment

      boolean hasEnchantment(@NotNull @NotNull org.bukkit.inventory.ItemStack item, @NotNull @NotNull org.bukkit.NamespacedKey key)
      Checks if an item has an enchantment by its key.
      Parameters:
      item - the item to check (must not be null)
      key - the enchantment's namespaced key (must not be null)
      Returns:
      true if the enchantment is present at any level
      Since:
      0.1.0
    • getEventBus

      @NotNull @NotNull EnchantmentEventBus getEventBus()
      Gets the event bus for subscribing to enchantment effects.

      Use this to listen for enchantment-triggered events without implementing a full effect handler.

      Returns:
      the event bus instance
      Since:
      0.1.0
    • getItemStorage

      @NotNull @NotNull ItemStorage getItemStorage()
      Gets the item storage for direct access to item enchantment operations.

      Use this for advanced item manipulation or when you need to perform batch operations on items.

      Returns:
      the item storage instance
      Since:
      0.1.0
    • query

      @NotNull @NotNull ItemEnchantmentQuery query()
      Gets the query facade for convenient enchantment lookups on items.

      This provides a scoped, developer-friendly API for checking enchantments without manual ItemMeta inspection. All methods are null-safe and return sensible defaults for null inputs.

      Example Usage:

      
       // Check if item has an enchantment
       if (api.query().hasEnchantment(item, lifeSteal)) {
           int level = api.query().getLevel(item, lifeSteal);
       }
      
       // Get all enchantments
       Map<EnchantmentDefinition, Integer> enchantments = api.query().getAllEnchantments(item);
      
       // Check material applicability
       Set<EnchantmentDefinition> applicable = api.query().getEnchantmentsFor(Material.DIAMOND_SWORD);
       
      Returns:
      the query facade instance
      Since:
      0.2.0
    • getPlugin

      @NotNull @NotNull org.bukkit.plugin.Plugin getPlugin()
      Gets the plugin that owns this API instance.
      Returns:
      the owning plugin
      Since:
      0.1.0
    • isFolia

      boolean isFolia()
      Checks if running on a Folia server.
      Returns:
      true if Folia region threading is detected
      Since:
      0.1.0
    • getVersion

      @NotNull @NotNull String getVersion()
      Gets the library version string.
      Returns:
      the version in semantic format (e.g., "1.0.0")
      Since:
      0.1.0
    • getScalingRegistry

      @NotNull @NotNull ScalingAlgorithmRegistry getScalingRegistry()
      Gets the scaling algorithm registry.

      Use this to register custom scaling algorithms or retrieve built-in ones. The registry is pre-populated with all built-in algorithms on startup.

      Returns:
      the scaling algorithm registry instance
      Since:
      0.2.0
    • getLootModifierRegistry

      @NotNull @NotNull LootModifierRegistry getLootModifierRegistry()
      Gets the loot modifier registry for block-break loot modifications.

      Use this registry to register LootModifier instances that can modify drops when blocks are broken with enchanted tools.

      Explicit Ownership: Only enchantments with explicitly registered modifiers affect loot drops. Non-targeted loot remains untouched unless opted in.

      Usage Example:

      
       LootModifierRegistry registry = api.getLootModifierRegistry();
      
       LootModifier myModifier = context -> {
           // Double drops based on level
           int multiplier = 1 + context.getLevel();
           for (ItemStack drop : context.getDrops()) {
               drop.setAmount(drop.getAmount() * multiplier);
           }
       };
      
       registry.register(myEnchantment, myModifier);
       
      Returns:
      the loot modifier registry instance
      Since:
      0.4.0
    • getScheduler

      @NotNull FoliaScheduler getScheduler()
      Gets the Folia-compatible scheduler for thread-safe task execution.

      Use this scheduler to run tasks on the appropriate threads:

      • Global region thread - for non-location-dependent operations
      • Region thread - for location-dependent operations
      • Entity scheduler - for entity-specific operations

      Usage Example:

      
       // Run later on global region thread
       api.getScheduler().runGlobalDelayed(plugin, () -> {
           // Task here
       }, 20L);
      
       // Run at a specific location's region thread
       api.getScheduler().runAtLocation(plugin, location, () -> {
           // Location-dependent task
       });
       
      Returns:
      the scheduler instance
      Since:
      0.2.0