> For the complete documentation index, see [llms.txt](https://docs.mongenscave.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.mongenscave.com/premium-products/mc-tycoonhoe/developer-api.md).

# Developer API

The **mc-TycoonHoe Developer API** allows external plugins to integrate with mc-TycoonHoe features such as player hoe statistics, essence, armor boosters, crystals, custom enchants, and plugin events.

The API is designed for Paper plugins and should be used as a `compileOnly` dependency.

***

### Available API Classes

| Class                   | Purpose                                                              |
| ----------------------- | -------------------------------------------------------------------- |
| `McTycoonHoeAPI`        | Main API for player hoe stats, prestige, essence, armor and boosters |
| `McTycoonHoeCrystalAPI` | Utility API for damaging crystals on cached hoes                     |
| `McTycoonHoeEnchantAPI` | API for registering, unregistering and reading custom enchants       |

***

### Package

```java
com.mongenscave.mctycoonhoe.api
```

***

## Installation

### Gradle Kotlin DSL

Add the MonGens Cave repository:

```kotlin
repositories {
    maven("https://repo.mongenscave.com/releases")
}
```

Add the API dependency:

```kotlin
dependencies {
    compileOnly("com.mongenscave:mc-TycoonHoeAPI:1.0.4")
}
```

### Maven

```xml
<repositories>
    <repository>
        <id>mongens-cave</id>
        <url>https://repo.mongenscave.com/releases</url>
    </repository>
</repositories>
```

```xml
<dependencies>
    <dependency>
        <groupId>com.mongenscave</groupId>
        <artifactId>mc-TycoonHoeAPI</artifactId>
        <version>1.0.4</version>
        <scope>provided</scope>
    </dependency>
</dependencies>
```

***

### Plugin Dependency

Your plugin must load after mc-TycoonHoe.

For `plugin.yml`:

```yaml
depend:
  - McTycoonHoe
```

If the installed plugin name is different in the plugin’s `plugin.yml`, use that exact name.

***

## Quick Start

### Accessing the Main API

```java
import com.mongenscave.mctycoonhoe.api.McTycoonHoeAPI;

public class ExampleService {

    private final McTycoonHoeAPI api = McTycoonHoeAPI.getInstance();

}
```

Most main API methods return `CompletableFuture`, because they may use database operations.

Do not block the server thread with `.join()` or `.get()`.

Correct usage:

```java
api.getEssence(player.getUniqueId()).thenAccept(essence -> {
    player.sendMessage("Your essence: " + essence);
});
```

If you need to run Bukkit API logic after an async callback, switch back to the server thread using your plugin scheduler.

***

## Core API

Class:

```java
McTycoonHoeAPI
```

Access:

```java
McTycoonHoeAPI api = McTycoonHoeAPI.getInstance();
```

***

### Methods

#### Get Highest Hoe Level

```java
CompletableFuture<Integer> getHighestHoeLevel(UUID owner)
```

Returns the highest hoe level owned by the player.

Example:

```java
api.getHighestHoeLevel(player.getUniqueId()).thenAccept(level -> {
    player.sendMessage("Highest hoe level: " + level);
});
```

***

#### Get Highest Prestige Level

```java
CompletableFuture<Integer> getHighestPrestigeLevel(UUID owner)
```

Returns the highest prestige level owned by the player.

Example:

```java
api.getHighestPrestigeLevel(player.getUniqueId()).thenAccept(prestige -> {
    player.sendMessage("Highest prestige: " + prestige);
});
```

***

#### Get Hoe Count

```java
CompletableFuture<Integer> getHoeCount(UUID owner)
```

Returns how many hoes the player owns.

Example:

```java
api.getHoeCount(player.getUniqueId()).thenAccept(count -> {
    player.sendMessage("You own " + count + " hoes.");
});
```

***

#### Get Essence

```java
CompletableFuture<Long> getEssence(UUID owner)
```

Returns the player’s essence amount.

If the player has no stored essence data, the API returns `0`.

Example:

```java
api.getEssence(player.getUniqueId()).thenAccept(essence -> {
    player.sendMessage("Essence: " + essence);
});
```

***

#### Give Essence

```java
CompletableFuture<Boolean> giveEssence(UUID owner, long amount)
```

Adds essence to a player.

Example:

```java
api.giveEssence(player.getUniqueId(), 500).thenAccept(success -> {
    if (success) {
        player.sendMessage("You received 500 essence.");
    }
});
```

***

#### Take Essence

```java
CompletableFuture<Boolean> takeEssence(UUID owner, long amount)
```

Attempts to remove essence from a player.

Returns `true` if the player had enough essence and the amount was removed.

Returns `false` if the player did not have enough essence.

Example:

```java
api.takeEssence(player.getUniqueId(), 250).thenAccept(success -> {
    if (success) {
        player.sendMessage("250 essence was removed.");
    } else {
        player.sendMessage("You do not have enough essence.");
    }
});
```

***

#### Get Active Armor

```java
CompletableFuture<Optional<String>> getActiveArmor(UUID player)
```

Returns the player’s active armor id, if one is equipped.

Example:

```java
api.getActiveArmor(player.getUniqueId()).thenAccept(activeArmor -> {
    activeArmor.ifPresentOrElse(
        armorId -> player.sendMessage("Active armor: " + armorId),
        () -> player.sendMessage("You do not have active armor.")
    );
});
```

***

#### Get Armor Booster

```java
double getArmorBooster(UUID player, String key)
```

Returns the current armor booster value for the player and booster key.

Example:

```java
double multiplier = api.getArmorBooster(player.getUniqueId(), "essence");
player.sendMessage("Essence booster: " + multiplier);
```

***

## Crystal API

Class:

```java
McTycoonHoeCrystalAPI
```

The Crystal API currently provides a static utility method for damaging a crystal inside a hoe.

***

### Damage Crystal

```java
McTycoonHoeCrystalAPI.damageCrystal(String hoeId, int crystalIndex, int amount);
```

Damages a crystal inside a specific hoe slot.

If the crystal reaches `0` durability, the crystal will be removed from the slot.

Example:

```java
McTycoonHoeCrystalAPI.damageCrystal(hoeId, 0, 1);
```

***

### Important Notes

This method silently does nothing if:

* the hoe is not currently cached
* the crystal slot does not exist
* the crystal slot is empty
* the crystal is already broken

Crystal indexes are slot-based. Make sure you use the correct crystal slot index from your own integration logic.

***

## Enchant API

Class:

```java
McTycoonHoeEnchantAPI
```

Access:

```java
McTycoonHoeEnchantAPI enchantApi = McTycoonHoeEnchantAPI.getInstance();
```

The Enchant API allows external plugins to register custom enchants into mc-TycoonHoe.

***

### Register Custom Enchant

```java
boolean register(CustomEnchant enchant)
```

Registers a custom enchant.

Returns:

| Value   | Meaning                                                      |
| ------- | ------------------------------------------------------------ |
| `true`  | The enchant was registered as a new enchant                  |
| `false` | An enchant with the same id already existed and was replaced |

The enchant id is case-insensitive and must be unique.

Example:

```java
McTycoonHoeEnchantAPI enchantApi = McTycoonHoeEnchantAPI.getInstance();

boolean fresh = enchantApi.register(new MyCustomEnchant());

if (fresh) {
    getLogger().info("Custom enchant registered.");
} else {
    getLogger().info("Custom enchant replaced an existing enchant.");
}
```

***

### Unregister Custom Enchant

```java
boolean unregister(String id)
```

Removes an API-registered enchant.

Built-in and config-defined enchants cannot be removed using this method.

Example:

```java
boolean removed = enchantApi.unregister("my_enchant");

if (removed) {
    getLogger().info("Custom enchant removed.");
}
```

***

### Check If Enchant Exists

```java
boolean isRegistered(String id)
```

Checks whether an enchant is currently registered.

This includes built-in, config-defined and API-registered enchants.

Example:

```java
if (enchantApi.isRegistered("fortune")) {
    player.sendMessage("Fortune enchant exists.");
}
```

***

### Get Enchant

```java
CustomEnchant get(String id)
```

Returns the registered enchant by id.

Returns `null` if no enchant exists with that id.

Example:

```java
CustomEnchant enchant = enchantApi.get("fortune");

if (enchant != null) {
    player.sendMessage("Enchant max level: " + enchant.maxLevel());
}
```

***

### Get Registered Enchant IDs

```java
Set<String> getRegisteredIds()
```

Returns an immutable snapshot of all registered enchant ids.

The returned ids are uppercase.

Example:

```java
Set<String> ids = enchantApi.getRegisteredIds();

for (String id : ids) {
    player.sendMessage("- " + id);
}
```

***

### Register Timing

Register custom enchants in your plugin’s `onEnable`.

Your plugin should depend on mc-TycoonHoe, otherwise the API may not be ready yet.

Example:

```java
@Override
public void onEnable() {
    McTycoonHoeEnchantAPI.getInstance().register(new MyCustomEnchant());
}
```

If mc-TycoonHoe is not fully enabled yet, the API can throw an `IllegalStateException`.

***

## Events

mc-TycoonHoe exposes multiple Bukkit events that can be listened to from external plugins.

Register listeners like normal Paper/Bukkit events.

Example:

```java
public final class ExampleListener implements Listener {

    @EventHandler
    public void onEssenceGain(EssenceGainEvent event) {
        // Your logic here
    }
}
```

Register the listener:

```java
Bukkit.getPluginManager().registerEvents(new ExampleListener(), this);
```

***

### General Events

Package:

```java
com.mongenscave.mctycoonhoe.api.event
```

Available events:

| Event                  | Description                                          |
| ---------------------- | ---------------------------------------------------- |
| `CropHarvestEvent`     | Called when a crop is harvested through mc-TycoonHoe |
| `EssenceGainEvent`     | Called when a player gains essence                   |
| `HoeXpGainEvent`       | Called when a hoe gains XP                           |
| `HoeLevelUpEvent`      | Called when a hoe levels up                          |
| `PrestigeLevelUpEvent` | Called when a hoe prestige level increases           |

Example:

```java
@EventHandler
public void onHoeLevelUp(HoeLevelUpEvent event) {
    // Reward, log or modify your own plugin data here
}
```

***

### Boss Events

Package:

```java
com.mongenscave.mctycoonhoe.api.event.boss
```

Available events:

| Event             | Description                         |
| ----------------- | ----------------------------------- |
| `BossStartEvent`  | Called when a boss encounter starts |
| `BossDamageEvent` | Called when a boss takes damage     |
| `BossEndEvent`    | Called when a boss encounter ends   |

Example:

```java
@EventHandler
public void onBossStart(BossStartEvent event) {
    // Custom boss start logic
}
```

***

### Condense Events

Package:

```java
com.mongenscave.mctycoonhoe.api.event.condense
```

Available events:

| Event                   | Description                                  |
| ----------------------- | -------------------------------------------- |
| `CondensePrepareEvent`  | Called before a condense action is completed |
| `CondenseCompleteEvent` | Called after a condense action is completed  |

Example:

```java
@EventHandler
public void onCondenseComplete(CondenseCompleteEvent event) {
    // Custom condense reward, logging or statistics logic
}
```

***

### Enchant Events

Package:

```java
com.mongenscave.mctycoonhoe.api.event.enchant
```

Available events:

| Event                          | Description                                    |
| ------------------------------ | ---------------------------------------------- |
| `EnchantPurchasePreEvent`      | Called before an enchant purchase is completed |
| `EnchantPurchaseCompleteEvent` | Called after an enchant purchase is completed  |

Example:

```java
@EventHandler
public void onEnchantPurchase(EnchantPurchaseCompleteEvent event) {
    // Custom logic after a player purchases an enchant
}
```

***

### Cancellable Events

Some events may implement Bukkit’s `Cancellable`.

If an event implements `Cancellable`, you can cancel it like this:

```java
@EventHandler
public void onEnchantPurchasePre(EnchantPurchasePreEvent event) {
    if (shouldBlockPurchase(event)) {
        event.setCancelled(true);
    }
}
```

Always check the event class or IDE autocomplete to see whether the event supports cancellation.

***

## Best Practices

### Do Not Block the Main Thread

Many API methods return `CompletableFuture`.

Avoid this:

```java
long essence = api.getEssence(player.getUniqueId()).join();
```

Use this instead:

```java
api.getEssence(player.getUniqueId()).thenAccept(essence -> {
    player.sendMessage("Essence: " + essence);
});
```

***

### Use `depend`, Not `softdepend`

If your plugin directly imports and uses mc-TycoonHoe API classes, use `depend`.

```yaml
depend:
  - McTycoonHoe
```

Use `softdepend` only if you check for the plugin before touching API classes.

***

### Validate Input

Always validate values before calling API methods.

Example:

```java
if (amount <= 0) {
    return;
}

api.giveEssence(player.getUniqueId(), amount);
```

***

### Register Enchants During Startup

Custom enchants should be registered during plugin startup.

Recommended:

```java
@Override
public void onEnable() {
    McTycoonHoeEnchantAPI.getInstance().register(new MyCustomEnchant());
}
```

Avoid registering enchants repeatedly during gameplay unless you intentionally want to replace an existing enchant.

***

### Handle Optional Values

Some API methods return `Optional`.

Example:

```java
api.getActiveArmor(player.getUniqueId()).thenAccept(optionalArmor -> {
    if (optionalArmor.isEmpty()) {
        player.sendMessage("No active armor.");
        return;
    }

    player.sendMessage("Active armor: " + optionalArmor.get());
});
```

***

## Full Example

```java
package com.example.myplugin;

import com.mongenscave.mctycoonhoe.api.McTycoonHoeAPI;
import com.mongenscave.mctycoonhoe.api.McTycoonHoeEnchantAPI;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;

public final class MyPlugin extends JavaPlugin {

    private McTycoonHoeAPI tycoonHoeApi;

    @Override
    public void onEnable() {
        this.tycoonHoeApi = McTycoonHoeAPI.getInstance();

        getLogger().info("mc-TycoonHoe API hooked successfully.");
    }

    public void sendPlayerStats(Player player) {
        tycoonHoeApi.getEssence(player.getUniqueId()).thenAccept(essence -> {
            player.sendMessage("Your essence: " + essence);
        });

        tycoonHoeApi.getHighestHoeLevel(player.getUniqueId()).thenAccept(level -> {
            player.sendMessage("Highest hoe level: " + level);
        });
    }
}
```

***

## Version

Current API artifact:

```txt
com.mongenscave:mc-TycoonHoeAPI:1.0.4
```

Recommended Java version:

```txt
Java 21
```

Recommended server platform:

```txt
Paper 1.21.8+
```
