# Welcome here!

You are probably stuck, need help, or just want to learn more about certain features related to the products. We strive for transparency and make it easy to navigate our documentation page.

If you have any questions or run into any issues, feel free to reach out to our developers on our Discord server, where you’ll receive 24/7 support.&#x20;

Join now: [click here](https://discord.gg/xKgazJgxSS)

### Jump right in

<table data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-cover data-type="files"></th><th data-hidden></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>DiscordLink Document</strong></td><td>Read more</td><td></td><td></td><td><a href="/pages/CyH2xJQs9yWJ1S8BYNav">/pages/CyH2xJQs9yWJ1S8BYNav</a></td></tr><tr><td>FunGun <strong>Document</strong></td><td>Read more</td><td></td><td></td><td><a href="/pages/YjJ2ZZ73c5l08LwzjVQv">/pages/YjJ2ZZ73c5l08LwzjVQv</a></td></tr><tr><td><strong>PlayerVisibility Document</strong></td><td>Read more</td><td></td><td></td><td><a href="/pages/zqdkYN0qM9vLPb7PLQZj">/pages/zqdkYN0qM9vLPb7PLQZj</a></td></tr></tbody></table>


# mc-TimesAPI

## 🕐 TimesAPI - Revolutionary Task Scheduling for Spigot Plugins and for Java projects!

Say goodbye to complex Bukkit schedulers and hello to human-readable task scheduling!<br>

### ❓ What is TimesAPI?

TimesAPI is a modern, lightweight Java scheduling library that transforms how you handle scheduled tasks in your Spigot plugins. Instead of wrestling with tick calculations and complex scheduler syntax, you can now schedule tasks using natural language like:

• "EVERYDAY @ 18:00" - Daily server restart warning\
• "EVERY MON,WED,FRI @ 12:00" - Periodic world saves\
• "EVERY 30 MINUTES" - Regular cleanup tasks\
• "WEEKDAYS @ 09:00" - Weekday-only announcements

### ⚡ Why TimesAPI for Spigot Development?

#### Traditional Bukkit Scheduler:

```java
// Confusing tick calculations and verbose syntax
Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, () -> {
// Daily restart warning
}, 20L * 60 * 60 * 24, 20L * 60 * 60 * 24); // 24 hours in ticks - confusing!
```

#### With TimesAPI:

<pre class="language-java"><code class="lang-java">TimesAPI scheduler = new TimesAPI();
scheduler.schedule("EVERYDAY @ 18:00", () -> { 
<strong>    Bukkit.broadcastMessage("§6Server restart in 1 hour!");
</strong>});
</code></pre>

### ⭐ Advanced Features for Plugin Developers

#### Annotation-Based Scheduling:&#xD;

```java
public class ServerTasks {
    @Schedule("EVERYDAY @ 06:00")
    public void dailyBackup() {
    backupPlayerData();
    backupWorldData();
    }
    
    @Schedule(value = "EVERY 5 MINUTES", async = true) 
    public void cleanupEntities() { 
    // Heavy cleanup task runs asynchronously 
    cleanupLaggyEntities(); 
    }
    
    @Schedule("WEEKDAYS @ 16:00") 
    public void schoolHoursEnd() { 
    Bukkit.broadcastMessage("§a[SCHOOL] School hours ended! Welcome back students!"); 
    }
}
```

```java
// Register in your plugin
TimesAPI scheduler = new TimesAPI();
scheduler.registerScheduledClass(new ServerTasks());


// Task Management:
// Cancel tasks dynamically
String taskId = scheduler.schedule("EVERY HOUR", () -> { 
    if (serverMaintenanceMode) { 
    return; // Skip during maintenance 
} 
performHourlyTasks();
}).get().getId();


// Cancel when needed
scheduler.cancelTask(taskId);
```

### ☀ Why Choose TimesAPI?

✅ No more tick calculations - use real-world time\
✅ Human-readable scheduling syntax\
✅ Thread-safe and performance optimized\
✅ Zero configuration required\
✅ Perfect for both simple and complex scheduling needs\
✅ Lightweight with 0 dependency!\
✅ Async support for heavy operations\
✅ Built-in error handling and recovery


# Installation

## 🚀 Quick Start

### Installation

Add **TimesAPI** to your project:

#### Maven

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

<dependencies>
    <dependency>
        <groupId>com.mongenscave</groupId>
        <artifactId>mc-TimesAPI</artifactId>
        <version>1.0.0</version>
    </dependency>
</dependencies>
```

#### Gradle

```groovy
repositories {
    maven {
        url "https://repo.mongenscave.com/releases"
    }
}

dependencies {
    implementation 'com.mongenscave:mc-TimesAPI:1.0.0'
}
```

> ⚠️ **Important:** Shadow JAR Required\
> TimesAPI requires proper shadowing to include all dependencies. Make sure to use the Shadow plugin in your build.

***

#### Gradle Shadow Plugin

```groovy
plugins {
    id 'com.github.johnrengelman.shadow' version '8.1.1'
}

shadowJar {
    archiveClassifier.set('')
    mergeServiceFiles()
}
```

***

#### Maven Shade Plugin

```xml
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <version>3.4.1</version>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>shade</goal>
            </goals>
        </execution>
    </executions>
</plugin>
```

***

### 🧪 Basic Usage

```java
import com.mongenscave.timesapi.TimesAPI;

public class MyApplication {
    public static void main(String[] args) {
        // Create TimesAPI instance
        TimesAPI scheduler = new TimesAPI();

        // Schedule a daily task
        scheduler.schedule("EVERYDAY @ 18:00", () -> {
            System.out.println("Daily backup started!");
        });

        // Schedule a weekly task
        scheduler.schedule("EVERY MON,WED,FRI @ 09:30", () -> {
            System.out.println("Weekly report generation");
        });

        // Don't forget to shutdown when your app closes
        Runtime.getRuntime().addShutdownHook(new Thread(scheduler::shutdown));
    }
}
```

***

Learn more @ [Github Repository](https://github.com/MonGen-s-Cave/mc-TimesAPI)


# mc-SmartSlotting

We use our newest slot technology to help our configurators work!

## Border

```yaml
item:
  slot: "border" # The GUI framework
  # etc...
```

## Chess

```yaml
item:
  slot: "chess:white" # Checkerboard sample
  # etc...
```

```yaml
item:
  slot: "chess:black" # Checkerboard sample
  # etc...
```

## Corners

```yaml
item:
  slot: "corners" # The 4 corners
  # etc...
```

## Center

```yaml
item:
  slot: "center" # The centre of the GUI
  # etc...
```

## Multiple Slot

```yaml
item:
  slot: "0,1,2,3,4"
  # etc...
```

## Range

```yaml
item:
  slot: "0-8" # From X to Y
  # etc...
```

## Grid

```yaml
item:
  slot: "grid:3x1" # 3x1 Grid
  # etc...
```

## Offset

```yaml
item:
  slot: "grid:3x2:offset:12" # 3 columns x 2 rows, starting from slot 12
  # etc...
```

## Edges

```yaml
item:
  slot: "edges" # Interior area without frame
  # etc...
```

## Directions

```yaml
item:
  slot: "top" # Top row
  # etc...
```

```yaml
item:
  slot: "bottom" # Bottom row
  # etc...
```

```yaml
item:
  slot: "left" # Left column
  # etc...
```

```yaml
item:
  slot: "right" # Right column
  # etc...
```

## Fill

```yaml
item:
  slot: "fill" # All free areas
  # etc...
```

## Priority

```yaml
item:
  slot: "border"
  priority: 1
  # etc...
item2:
  slot: "fill"
  priority: -1 # last time
```


# mc-DiscordLink

Make the connection between minecraft and discord more interactive!

<figure><img src="/files/9dQwjucgHqUORdneSQzc" alt=""><figcaption></figcaption></figure>

### Plugin Features

* Multiple plugin support
* Up-to-date plugin
* LuckPerms rank synchronization to Discord
* Secure 2FA system
* Optimized plugin, does not cause lag
* Ability to reward Discord server boosters, Boost Rewards
* Sync rewards
* Public Slash commands
* /profile command for both Minecraft and Discord
* Very active support, developers
* Fully customizable config, messages, and embeds
* Very fast plugin response time between Discord and Minecraft

{% hint style="info" %}
Whatever complex request you have for the plugin, we will solve it for you!
{% endhint %}


# Plugin FAQ

Here are the features of the plugin, along with answers to frequently asked questions

### I installed the plugin but it won't start and I see a big error message on the console. What to do?

* **The Answer Is:** When you make such a mistake, don't worry, because it's understandably repulsive. What happens is that you have filled in something incorrectly within config.yml. Most likely you have not entered your Discord Bot token or it is invalid. Please check in the config file.&#x20;

```yaml
discord:
  token: 'set the token here'
  guild-id: 'set the guild id here'
  change-nickname: true # optional feature
  restrict-to-channel: false # optional feature
  target-channel-id: 'channel-id'
```

### What if I have several servers in my network and I want to be able to use the plugin everywhere? Does the plugin support Bungecord or other proxy software?

* **The Answer Is:** Currently the plugin does not support proxy software directly and you cannot use the plugin on a proxy server, but you can fully use the functionality if you put the plugin on all servers and use a MySQL database. In this case it is like using the plugin on a proxy server.

```yaml
storage:
  #  driver: sqlite / mysql
  driver: 'mysql' # Use MySQL
  host: 'database-host'
  port: '3306'
  name: 'database-name'
  username: 'database-username'
  password: 'database-password'

  pool: # HikariCP config (Do not edit if you do not know what it is)
    maximumPoolSize: 10
    minimumIdle: 5
    connectionTimeout: 30000
    maxLifetime: 1800000
    idleTimeout: 600000
```

### Can the plugin sync Minecraft ranks and assign them to people on Discord? How does it work exactly?

* **The Answer Is:** Exactly. The plugin is able to sync player ranks to Discord. Currently, it only works if you are using the LuckPerms plugin but we would like to expand this to include more plugins in the future. (If the plugin you are using is not currently supported, don't worry as we will fix your problem) Before it works properly, we want to clarify that the plugin CANNOT assign Discord ranks to players in Minecraft. It is incredibly simple to use. Create a rank you want to assign to people who are synced together and follow the instructions in config.yml.

```yaml
role-sync:
  default: 'default-discord-role-id' # Here the ingame rank name and the Discord rank ID equivalent
  mvp: 'mvp-discord-role-id'
```


# Commands

The current commands in the plugin

| Command                      | Permission                        | Description                                            |
| ---------------------------- | --------------------------------- | ------------------------------------------------------ |
| /link                        | discordlink.link                  | Use generated activation code.                         |
| /unlink                      | discordlink.unlink                | Unlink your accounts.                                  |
| /2fa                         | discordlink.2fa                   | Switch Two Factor authentication on your account.      |
| /profile                     | discordlink.profile               | Check your profile.                                    |
| /boostrewards                | discordlink.boostrewards          | Claim your Boost rewards.                              |
|                              |                                   |                                                        |
| /discordlink reload          | discordlink.admin.reload          | Reload the plugin files.                               |
| /discordlink forceunlink     | discordlink.admin.forceunlink     | Force unlink somebody account.                         |
| /discordlink forcereset      | discordlink.admin.forcereset      | Force reset somebody rewards.                          |
| /discordlink forcesyncupdate | discordlink.admin.forcesyncupdate | Force a synchronization update for all synced players. |
| /discordlink migration       | discordlink.admin.migration       | Migrate data to DiscordLink from another plugin.       |


# Feature Help


# Setup Discord Bot

Follow the guide to perfectly set up your Discord Bot and avoid any issues!

## Create a New Discord Bot&#x20;

Follow the guide carefully, as the bot requires specific permissions and intents to function smoothly!

1. Log into the [Discord Developer Portal](https://discord.com/developers/applications) and click the '**New Application**' button in the top right corner.
2. Give your bot a name of your choice (you can edit it later if needed).
3. After creating the bot, you'll find yourself in a dashboard. Here, select the 'Bot' option in the sidebar, scroll down slightly, and enable all intents for the bot under the 'Privileged Gateway Intents' section (Presence Intent, Server Members Intent, Message Content Intent).
4. Next, go to the 'OAuth2' option in the sidebar, then within it, go to 'OAuth2 URL Generator.' Check the following options: 'bot,' 'applications.commands.' Scroll down a bit and assign the desired permissions to the bot (Recommended: Administrator).
5. On the same page, scroll all the way down, and use the provided link to invite your Discord bot to the server. B.1: In the Developer Portal, return to the 'Bot' section if you need your bot’s token, and there you can either copy it or request a new one (Reset Token). Place the provided Discord bot token in the config.yml file under the 'discord' section in the 'token' field. (Fill in the other fields as well. Important: guild-id)

{% hint style="success" %}
If you have any questions or need help, feel free to contact us on our [Discord server](https://dc.mongenscave.com/)!
{% endhint %}


# Bot Settings

Starting from v2.7.0, DiscordLink introduces a dedicated bot presence manager that allows dynamic and configurable activity/status updates for your Discord bot.

## 🔧 Custom Discord Bot Presence

The `bot-settings` section in the `config.yml` allows you to customize the **activity** and **online status** of the Discord bot managed by the plugin.

This feature supports **PlaceholderAPI placeholders**, enabling dynamic values such as total player count across servers (e.g. `%bungee_total%`).

⚠️ Multi-Server Support Notice

If you run this plugin on **multiple Minecraft servers (multi-server setup)** with the same Discord bot token, you **must enable `bot-settings.enabled: true` on only ONE server**.\
Having this enabled on more than one server **may result in duplicate status updates or Discord rate-limiting**.

## 📁 Configuration

Add or edit the following section in your `config.yml`:

```yaml
discord:
  token: "your-discord-bot-token"
  guild-id: "your-guild-id"

  bot-settings:
    # ⚠️ ENABLE WITH CAUTION!
    # Only one server should manage bot presence if you're running multiple servers.
    enabled: true

    # The text to display as the bot's activity.
    # PlaceholderAPI placeholders (e.g. %bungee_total%) are supported.
    activity: "Playing with %bungee_total% players"

    # The type of activity:
    # Options: PLAYING, WATCHING, LISTENING, COMPETING
    activity-type: "PLAYING"

    # The bot's online status:
    # Options: ONLINE, IDLE, DND, INVISIBLE
    status: "ONLINE"

  change-nickname: true
  restrict-to-channel: true
  target-channel-id: "your-channel-id"
```

## 🔁 Live Updating with Placeholders

If `activity` contains **PlaceholderAPI placeholders**, they are parsed automatically using your installed placeholder expansions.

#### 🔄 Refresh Frequency:

* The activity text is refreshed:
  * **60 ticks** after startup (3 seconds)
  * **every 3 minutes** afterwards (asynchronously)
* No update is sent unless the placeholder-resolved text has changed, avoiding unnecessary API calls.

## 🔍 Example Output

If you use the following:

```yaml
activity: "Playing with %bungee_total% players"
activity-type: "PLAYING"
status: "ONLINE"
```

Your bot will display:

> **Playing with 124 players**

And its status will appear as **Online**.


# Link System

The plugin provides two functions that allow players to generate a code.

## Default Configuration

This is the default configuration, you can choose type between SLASH and LINK-EMBED

```yaml
link-system:
  # Types: SLASH, LINK-EMBED
  type: SLASH

  slash-command:
    link:
      command: "link"
      description: "Generate an activation code to sync!"
    link-embed:
      command: "link-embed"
      description: "The channel to send the linking embed message!"

  link-rewards:
    give-discord-role: "your-role-id"
    once-reward: true
    sync-roles: true

    execute-commands:
      enabled: true
      only-if-player-online: true
      commands:
        - "eco give %player% 150"
        - "say %player% has successfully synced!"
```

## Type: SLASH

This system registers a simple slash command that users can use to generate a code.

Illustration on Discord:

<figure><img src="/files/VUDECM4O83UshTMgwu0v" alt=""><figcaption></figcaption></figure>

## Type: LINK-EMBED

With the `/link-embed #channel` slash command, users with Administrator permissions can send an embed message to a specified channel. By clicking the button in the embed, they can generate their own linking code.

Illustration on Discord:

<figure><img src="/files/PZzw7uPKAVMpByV9KMnb" alt=""><figcaption></figcaption></figure>


# Embed Builder

This plugin allows you to fully customize Discord embed messages using simple YAML configuration files.  Here is a complete guide on what you can edit and how to do it.

### ✏️ Available Embed Options

| Key               | Description                                              |
| ----------------- | -------------------------------------------------------- |
| `title`           | The main title of the embed.                             |
| `description`     | The main text. Use  for line breaks.                     |
| `color`           | Embed color in HEX format (example: `#00FFFF`).          |
| `url`             | Makes the title clickable, linking to the specified URL. |
| `timestamp`       | If `true`, adds the current timestamp.                   |
| `author.name`     | Displays an author name at the top of the embed.         |
| `author.url`      | (Optional) URL linked to the author name.                |
| `author.icon_url` | (Optional) Icon shown next to the author name.           |
| `thumbnail`       | Small image displayed on the right side.                 |
| `image`           | Large image displayed under the description.             |
| `footer.text`     | Footer text displayed at the bottom.                     |
| `footer.icon_url` | (Optional) Icon next to the footer text.                 |
| `fields`          | Adds multiple custom name/value fields.                  |

### 🔹 How to Use Author, Footer, and Fields

**Author example:**

```yaml
author:
  name: "Server Name"
  url: "https://yourserver.com"
  icon_url: "https://yourserver.com/icon.png"
```

* `author.name` is **required** if you want to show an author.
* `url` and `icon_url` are **optional**.

**Footer example:**

```yaml
footer:
  text: "MonGen's Cave"
  icon_url: "https://yourserver.com/footer-icon.png"
```

* `footer.text` is **required** for a footer to appear.
* `icon_url` is optional.

**Fields example (optional):**

```yaml
fields:
  - name: "First Field"
    value: "This is a value."
    inline: true
  - name: "Second Field"
    value: "Another value."
    inline: false
```

* `name`: Title of the field.
* `value`: Text inside the field.
* `inline`: Whether the field should be shown next to others (`true`) or on a new line (`false`).

### 🎨 Notes and Tips

* **Color must start with `#`**, otherwise the embed will use a default color.
* **Line breaks** inside description: use `\n`.
* If a field or option is missing, it will simply not be shown — no errors.
* Always check that URLs and image links are valid.

### ✅ Minimal Working Example

```yaml
title: "Welcome!"
description: "Thank you for joining our server!\nEnjoy your stay!"
color: "#00FFFF"
timestamp: true

author:
  name: "MonGen's Cave"
  icon_url: "https://yourserver.com/author-icon.png"

thumbnail: "https://yourserver.com/thumbnail.png"

footer:
  text: "MonGen's Cave - 2025"

fields:
  - name: "Getting Started"
    value: "Visit our website for guides!"
    inline: false
```


# Supported Plugins

Current active placeholders for the plugin

| Placeholder                         | Output                    |
| ----------------------------------- | ------------------------- |
| %discordlink\_player\_synced%       | true/false (customizable) |
| %discordlink\_player\_synced\_raw%  | true/false boolean        |
|                                     |                           |
| %discordlink\_discord\_id%          | user discord id           |
| %discordlink\_discord\_username%    | user discord name         |
| %discordlink\_discord\_nickname%    | user nickname on server   |
|                                     |                           |
| %discordlink\_guild\_member\_count% | the guild member count    |

{% hint style="info" %}
If you have an idea for a new placeholder, please contact us! [Click Here](https://discord.gg/xKgazJgxSS)
{% endhint %}


# Rank Plugins

The plugin use Rank plugins for Role Sync System

## List of Plugins

To change the rank plugin edit the hooks.yml.

```yaml
hooks:
  settings:
    # Which rank plugin are you using on your server?
    rank-plugin: LuckPerms

  register:
    LuckPerms: true
    UltraPermissions: false

version: 1
```

* LuckPerms [\[Download\]](https://luckperms.net/download) (Free)
* UltraPermissions [\[Download\]](https://www.spigotmc.org/resources/ultra-permissions.42678/) (Free)

## Planned Plugins

* PowerRanks
* GroupManager

{% hint style="warning" %}
Don't worry if you don't see the plugin you're using here. Contact us and we'll integrate it for you right away! Join our Discord server and let us know. [\[Join Discord\]](https://discord.gg/xKgazJgxSS)
{% endhint %}


# PlaceholderAPI

Current active placeholders for the plugin

| Placeholder                         | Output                    |
| ----------------------------------- | ------------------------- |
| %discordlink\_player\_synced%       | true/false (customizable) |
| %discordlink\_player\_synced\_raw%  | true/false boolean        |
|                                     |                           |
| %discordlink\_discord\_id%          | user discord id           |
| %discordlink\_discord\_username%    | user discord name         |
| %discordlink\_discord\_nickname%    | user nickname on server   |
|                                     |                           |
| %discordlink\_guild\_member\_count% | the guild member count    |

{% hint style="success" %}
If you have an idea for a new placeholder, please contact us! [\[Join Discord\]](https://discord.gg/xKgazJgxSS)
{% endhint %}


# DiscordLinkProxy

Add an addon to the plugin to make it even better!

### How can i download the addon?

* Currently only available on the BuiltByBit [**DiscordLink**](https://builtbybit.com/resources/discordlink-all-in-one-discord-sync.38922/) page and [SpigotMC](https://www.spigotmc.org/resources/discordlinkproxy-discordlink-free-proxy-addon.120786/).

### What does this addon do?

* **The Answer Is:** This addon helps the plugin to burn out, fix and help in spaces where the plugin itself is unable to reach. The addon currently handles and disables the use of bungee/velocity commands before 2FA confirmation!

#### Default Configuration

```yaml
prefix: "<b><gradient:#6C78F6:#A7AFFF>DISCOR</gradient><gradient:#A7AFFF:#6C78F6>DLINK</gradient></b> <dark_gray>»</dark_gray>"

auth-server:
  - auth

whitelisted-commands:
  # Kick player when try to use not whitelisted command
  player-kick:
    enabled: true
    message:
      - "<b><gradient:#B50404:#FF0000>YOU HAVE BEEN KICKED</gradient></b>"
      - ""
      - "<gray>You have been kicked from the server.</gray>"
      - "<yellow>Reason:</yellow> <white>Use command without 2FA confirm</white>"
      - ""
      - "<gold>Feel free to contact with us.</gold>"
      - "<dark_gray>ᴅɪꜱᴄᴏʀᴅ @ ᴅᴄ.ᴍᴏɴɢᴇɴꜱᴄᴀᴠᴇ.ᴄᴏᴍ</dark_gray>"
  allowed-commands: # []
    - 'glist'


version: '1'
```

### mc-DiscordLinkProxy Addon

* This addon support Velocity and Bungeecord.
* Available from DiscordLink 2.2.0 version only.
* Only MiniMessage format available!


# Floodgate

If you are using GeyserMC and have Bedrock players it is recommended to use Floodgate.

## Enable the Floodgate Hook

Enable the floodgate in the hooks.yml

```yaml
hooks:
  settings:
    ...
    ...
    ...

  register:
    Floodgate: true

version: 1
```

This system manages a JAVA-based UUID for Bedrock players. If you encounter any problems please contact us. It is recommended to use it because the UUID of Bedrock players can change in cases that cause problems for the sync system.

{% hint style="danger" %}
This system is in the BETA phase! If you encounter a problem contact us on Discord! [\[Join Discord\]](https://discord.gg/xKgazJgxSS)
{% endhint %}


# Migrate Data

The mc-DiscordLink gives you the possibility to replace other similar plugins and save your users' data. Ability to convert data from other plugins to mc-DiscordLink

## Migrate Command

| Command              | Permission          | Description                                      |
| -------------------- | ------------------- | ------------------------------------------------ |
| /discordlink migrate | discordlink.migrate | Migrate data to DiscordLink from another plugin. |

## Supported Plugins

* DiscordSRV
* gDiscordSync (old, outdated and no longer available version of mc-DiscordLink)

{% hint style="danger" %}
During the data migration, both plugins (mc-DiscordLink and another plugin) must be present. Do not shut down the server during migration!
{% endhint %}

## Migrate Guide

1. Upload the mc-DiscordLink and restart the server.
2. Now set up DiscordLink and make sure you are using the database you want.
3. Use the /discordlink migrate command and wait the migration..
4. It is recommended to restart the server and remove the other plugin.
5. Everything is ready! You switched to a better plugin and preserved your users' data!


# mc-KillStats

Make the connection between minecraft and discord more interactive!

<figure><img src="/files/9dQwjucgHqUORdneSQzc" alt=""><figcaption></figcaption></figure>

### Plugin Features

* Multiple plugin support
* Up-to-date plugin
* LuckPerms rank synchronization to Discord
* Secure 2FA system
* Optimized plugin, does not cause lag
* Ability to reward Discord server boosters, Boost Rewards
* Sync rewards
* Public Slash commands
* /profile command for both Minecraft and Discord
* Very active support, developers
* Fully customizable config, messages, and embeds
* Very fast plugin response time between Discord and Minecraft

{% hint style="info" %}
Whatever complex request you have for the plugin, we will solve it for you!
{% endhint %}


# Plugin FAQ

Here are the features of the plugin, along with answers to frequently asked questions

### I installed the plugin but it won't start and I see a big error message on the console. What to do?

* **The Answer Is:** When you make such a mistake, don't worry, because it's understandably repulsive. What happens is that you have filled in something incorrectly within config.yml. Most likely you have not entered your Discord Bot token or it is invalid. Please check in the config file.&#x20;

```yaml
discord:
  token: 'set the token here'
  guild-id: 'set the guild id here'
  change-nickname: true # optional feature
  restrict-to-channel: false # optional feature
  target-channel-id: 'channel-id'
```

### What if I have several servers in my network and I want to be able to use the plugin everywhere? Does the plugin support Bungecord or other proxy software?

* **The Answer Is:** Currently the plugin does not support proxy software directly and you cannot use the plugin on a proxy server, but you can fully use the functionality if you put the plugin on all servers and use a MySQL database. In this case it is like using the plugin on a proxy server.

```yaml
storage:
  #  driver: sqlite / mysql
  driver: 'mysql' # Use MySQL
  host: 'database-host'
  port: '3306'
  name: 'database-name'
  username: 'database-username'
  password: 'database-password'

  pool: # HikariCP config (Do not edit if you do not know what it is)
    maximumPoolSize: 10
    minimumIdle: 5
    connectionTimeout: 30000
    maxLifetime: 1800000
    idleTimeout: 600000
```

### Can the plugin sync Minecraft ranks and assign them to people on Discord? How does it work exactly?

* **The Answer Is:** Exactly. The plugin is able to sync player ranks to Discord. Currently, it only works if you are using the LuckPerms plugin but we would like to expand this to include more plugins in the future. (If the plugin you are using is not currently supported, don't worry as we will fix your problem) Before it works properly, we want to clarify that the plugin CANNOT assign Discord ranks to players in Minecraft. It is incredibly simple to use. Create a rank you want to assign to people who are synced together and follow the instructions in config.yml.

```yaml
role-sync:
  default: 'default-discord-role-id' # Here the ingame rank name and the Discord rank ID equivalent
  mvp: 'mvp-discord-role-id'
```


# Supported Plugins

Here are the current plugins that DiscordLink supports.

### Rank System

* LuckPerms

* UltraPermissions

* Planned plugins:
  * PowerRanks
  * GroupManager

### Other

* PlaceholderAPI
* DiscordLinkProxy [\[Addon\]](/premium-products/discordlink/supported-plugins/discordlinkproxy)


# Commands

The current commands in the plugin

| Command                      | Permission                        | Description                                            |
| ---------------------------- | --------------------------------- | ------------------------------------------------------ |
| /link                        | discordlink.link                  | Use generated activation code.                         |
| /unlink                      | discordlink.unlink                | Unlink your accounts.                                  |
| /2fa                         | discordlink.2fa                   | Switch Two Factor authentication on your account.      |
| /profile                     | discordlink.profile               | Check your profile.                                    |
| /boostrewards                | discordlink.boostrewards          | Claim your Boost rewards.                              |
|                              |                                   |                                                        |
| /discordlink reload          | discordlink.admin.reload          | Reload the plugin files.                               |
| /discordlink forceunlink     | discordlink.admin.forceunlink     | Force unlink somebody account.                         |
| /discordlink forcereset      | discordlink.admin.forcereset      | Force reset somebody rewards.                          |
| /discordlink forcesyncupdate | discordlink.admin.forcesyncupdate | Force a synchronization update for all synced players. |
| /discordlink migration       | discordlink.admin.migration       | Migrate data to DiscordLink from another plugin.       |


# Hooks

Current active placeholders for the plugin

| Placeholder                         | Output                    |
| ----------------------------------- | ------------------------- |
| %discordlink\_player\_synced%       | true/false (customizable) |
| %discordlink\_player\_synced\_raw%  | true/false boolean        |
|                                     |                           |
| %discordlink\_discord\_id%          | user discord id           |
| %discordlink\_discord\_username%    | user discord name         |
| %discordlink\_discord\_nickname%    | user nickname on server   |
|                                     |                           |
| %discordlink\_guild\_member\_count% | the guild member count    |

{% hint style="info" %}
If you have an idea for a new placeholder, please contact us! [Click Here](https://discord.gg/xKgazJgxSS)
{% endhint %}


# PlaceholderAPI


# Developer API

Use the KillStats API to retrieve player statistics and validate kills! (Anti Killfarm)

### Add the Dependency

Don't forget to change always the version!

<div align="left"><img src="https://img.shields.io/maven-metadata/v.svg?label=KillStatsAPI&#x26;metadataUrl=https://repo.mongenscave.com/releases/com/mongenscave/mc-KillStatsAPI/maven-metadata.xml" alt=""></div>

{% tabs %}
{% tab title="Maven" %}

<pre class="language-xml" data-full-width="true"><code class="lang-xml"><strong>&#x3C;repository>
</strong>  &#x3C;id>MonGens-Cave&#x3C;/id>
  &#x3C;url>https://repo.mongenscave.com/releases&#x3C;repository>&#x3C;/url>
&#x3C;/repository>

&#x3C;dependency>
  &#x3C;groupId>com.mongenscave&#x3C;/groupId>
  &#x3C;artifactId>mc-KillStatsAPI&#x3C;/artifactId>
  &#x3C;version>[VERSION]&#x3C;/version>
&#x3C;/dependency>
</code></pre>

{% endtab %}

{% tab title="Gradle" %}

```groovy
maven { url "https://repo.mongenscave.com/releases" }

implementation "com.mongenscave:mc-KillStatsAPI:[VERSION]"
```

{% endtab %}
{% endtabs %}

### Add mc-KillStats to plugin.yml

{% tabs %}
{% tab title="as depend" %}

```yaml
depend:
  - mc-KillStats
```

{% endtab %}

{% tab title="as softdepend" %}

```yaml
softdepend:
  - mc-KillStats
```

{% endtab %}
{% endtabs %}

### Example how to use the KillStatsAPI

For example, use the Anti Killfarm system and validate kills with the API!

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

boolean valid = api.isValidKill("Player1", "Player2");
if (valid) {
    System.out.println("This is a valid kill!");
} else {
    System.out.println("Invalid kill!");
}
```


# mc-Levels

Get more out of leveling up, make it spectacular with this plugin!

<figure><img src="/files/KxAd835qwsfAGHRWiFJZ" alt=""><figcaption></figcaption></figure>

### Plugin Features

* Multiple Server Support
* MySQL, H2 and SQLite Support
* Folia Support
* Up-to-date plugin
* XP Booster, Supports AxBooster
* Secure XP and Level Gain
* Optimized plugin, does not cause lag
* Very active support, developers
* HEX Color Support
* Unlimited Levels&#x20;
* Level Card Support
* Modern and Fast plugin

{% hint style="info" %}
Whatever complex request you have for the plugin, we will solve it for you!
{% endhint %}


# Plugin FAQ

Here are the features of the plugin, along with answers to frequently asked questions

### Why should you use mc-Levels?

* **The Answer Is:** mc-Levels is a highly innovative, next-generation plugin that is always up to date. It supports servers with custom textures and is optimized for them. With its versatile and modern solutions, the plugin offers a seamless experience and includes many unique features that no other plugin can provide.

### How many levels can the plugin handle at maximum?

* **The Answer Is:** The plugin can currently handle an unlimited number of levels, even up to 1 million, seamlessly and flawlessly. It is highly optimized, ensuring fast processing and loading of level rewards and possible overrides.

{% hint style="success" %}
If you have any questions or need help, feel free to contact us on our [Discord server](https://dc.mongenscave.com)!
{% endhint %}


# Commands

The current commands in the plugin.

## Player Commands

| Command                | Permission                                         | Description                                 |
| ---------------------- | -------------------------------------------------- | ------------------------------------------- |
| /levels info \[player] | mclevels.info.self mclevels.info.others            | View your own or someone else's statistics. |
| /levels help           | <p>mclevels.player.help<br>mclevels.admin.help</p> | Help for plugin commands.                   |

## Admin Commands

| Command                               | Permission               | Description                 |
| ------------------------------------- | ------------------------ | --------------------------- |
| /levels addxp \<player> \<amount>     | mclevels.admin.addxp     | Give XP to a player.        |
| /levels setxp \<player> \<amount>     | mclevels.admin.setxp     | XP setting for a player.    |
| /levels takexp \<player> \<amount>    | mclevels.admin.takexp    | Taking XP from a player.    |
|                                       |                          |                             |
| /levels addlevel \<player> \<amount>  | mclevels.admin.addlevel  | Give Level to a player.     |
| /levels setlevel \<player> \<amount>  | mclevels.admin.setlevel  | Level setting for a player. |
| /levels takelevel \<player> \<amount> | mclevels.admin.takelevel | Taking Level from a player. |
|                                       |                          |                             |
| /levels reset \<player>               | mclevels.admin.reset     | Reset someone statistics.   |
| /levels reload                        | mclevels.admin.reload    | Reload the plugin files.    |


# Supported Plugins

{% content-ref url="/pages/DED4SrmkHwhlgF1olCZf" %}
[AxBooster](/premium-products/levels/supported-plugins/axbooster)
{% endcontent-ref %}

{% content-ref url="/pages/rGhb3cpur9f5XEodKinY" %}
[PlaceholderAPI](/premium-products/levels/supported-plugins/placeholderapi)
{% endcontent-ref %}


# PlaceholderAPI

Current active placeholders for the plugin

## Player Placeholders

| Placeholder                           | Output                              |
| ------------------------------------- | ----------------------------------- |
| %mclevels\_player\_level%             | Shows the player's formatted level. |
| %mclevels\_player\_level\_raw%        | Displays the player's raw level.    |
| %mclevels\_player\_xp%                | Shows the player's current XP.      |
| %mclevels\_player\_xp\_required%      | Displays XP needed for next level.  |
| %mclevels\_player\_xp\_remaining%     | Shows XP left to level up           |
| %mclevels\_player\_next\_level\_xp%   | Shows XP left to level up           |
| %mclevels\_player\_xp\_progress\_bar% | Displays XP progress as a bar.      |
| %mclevels\_player\_xp\_percent%       | Shows XP progress (%)               |

## Other Placeholders

| Placeholder            | Output                      |
| ---------------------- | --------------------------- |
| %mclevels\_max\_level% | Displays the maximum level. |


# AxBooster

The plugin support AxBooster and have XP booster option.

## 1) AxBooster Hook

Enable the "AxBooster" in the hooks.yml and restart the server.

```yaml
hooks:
  settings:
    ...
    ...
    ...

  register:
    AxBooster: true

version: 1
```

## 2) mc-Levels Integration

After restarting the server, make sure that the AxBooster hooks.yml file contains the following code snippet:

```yaml
  mclevels:xp:
    enabled: true
    display-name: '&#00FFFFmclevels&f:&#00FF00xp'
```

## 3) Create a Booster

Everything is ready. Create your own booster and use mc-Levels to boost your players' XP gain. (AxBooster/boosters/yourxpbooster.yml example)

```yaml
# DOCUMENTATION: https://docs.artillex-studios.com/axboosters.html
# ITEM BUILDER: https://docs.artillex-studios.com/item-builder.html

display-name: "&#44FFFF&l%multiplier% xᴘ ʙᴏᴏsᴛᴇʀ"

# the icon shown in guis
icon:
  type: EMERALD

# which plugins should this booster affect?
# list of supported plugins: https://docs.artillex-studios.com/axboosters-supported-plugins.html#booster-hooks
boosted:
  - "mclevels:xp"
```


# Developer API

Provides an easy way to manage player levels and XP, handle level-up events, and control XP gains.

### 1) Add the Dependency

Don't forget to change always the version!

<div align="left"><figure><img src="https://img.shields.io/maven-metadata/v.svg?label=LevelsAPI&#x26;metadataUrl=https://repo.mongenscave.com/releases/com/mongenscave/mc-LevelsAPI/maven-metadata.xml" alt="" width="188"><figcaption></figcaption></figure></div>

{% tabs %}
{% tab title="Maven" %}

<pre class="language-xml" data-full-width="true"><code class="lang-xml"><strong>&#x3C;repository>
</strong>  &#x3C;id>MonGens-Cave&#x3C;/id>
  &#x3C;url>https://repo.mongenscave.com/releases&#x3C;repository>&#x3C;/url>
&#x3C;/repository>

&#x3C;dependency>
  &#x3C;groupId>com.mongenscave&#x3C;/groupId>
  &#x3C;artifactId>mc-LevelsAPI&#x3C;/artifactId>
  &#x3C;version>[VERSION]&#x3C;/version>
&#x3C;/dependency>
</code></pre>

{% endtab %}

{% tab title="Gradle" %}

```groovy
maven { url "https://repo.mongenscave.com/releases" }

implementation "com.mongenscave:mc-LevelsAPI:[VERSION]"
```

{% endtab %}
{% endtabs %}

### 2) Add mc-Levels to plugin.yml

{% tabs %}
{% tab title="as depend" %}

```yaml
depend:
  - mc-Levels
```

{% endtab %}

{% tab title="as softdepend" %}

```yaml
softdepend:
  - mc-Levels
```

{% endtab %}
{% endtabs %}

### 3) Example how to use the LevelsAPI

As an example, give XP to a player.

```java
public class XPExample {
    public void giveXP(Player player, int amount) {
        LevelsAPI.getInstance().addXP(player, amount);
        player.sendMessage("✅ " + amount + " You got XP!");
    }
}
```

| Event              | Description                                                    |
| ------------------ | -------------------------------------------------------------- |
| PlayerGainXPEvent  | Triggered when a player gains XP. Can be modified or canceled. |
| PlayerLevelUpEvent | Fired when a player levels up.                                 |


# mc-Credits

Manage your server's currency with a modern and secure solution!

<figure><img src="/files/kN9qiuUkDPkiSbPSd7C9" alt=""><figcaption></figcaption></figure>

### Plugin Features

* Fully customizable
* MySQL and SQLite support
* Multi-server support
* PlaceholderAPI support
* Customizable placeholder
* Leaderboard placeholders
* Customizable command
* Discord webhook
* Unlimited categories and products
* Highly optimized
* Purchase log
* Hex color support
* Fully customizable menus
* Anti-credit dupe system
* Discount system and commands (all, category, and product)
* Confirm menu (optional)
* Command cooldowns
* Minimum and maximum requirements for credit commands
* Developer-friendly configuration
* Developer-friendly API

{% hint style="info" %}
Whatever complex request you have for the plugin, we will solve it for you!
{% endhint %}


# Plugin FAQ

Here are the features of the plugin, along with answers to frequently asked questions

### How can I change the plugin command?

* **The Answer Is:** Edit the commands section and restart the server.\
  `The plugin commands (restart the server to change)`\
  &#x20; `commands:`\
  &#x20;`- "mycommand"`\
  &#x20;`- "mycmd"`

### How can I edit the discounts?

* **The Answer Is: Find the `discounts.yml` file in the plugin's folder, edit the desired section, and save the file.**\
  \
  **Options:**<br>
  * **type**: `all` (all products in the shops), `category` (only the specified category), `item` (only the specified item)
  * **id**: The name of the category or the ID of the item (category/product). If you apply an "all" type discount, this option is not required.
  * **discount\_type**: `percentage` (e.g., -25% off the product price), `absolute` (e.g., -200 credits off the product price
  * **amount**: The value of the discount (e.g., 25, 200)

{% hint style="success" %}
If you have any questions or need help, feel free to contact us on our [Discord server](https://dc.mongenscave.com)!
{% endhint %}


# Commands

The current commands in the plugin.

## Player Commands

| Command                            | Permission                                                  | Description                                        |
| ---------------------------------- | ----------------------------------------------------------- | -------------------------------------------------- |
| /mccredits pay \<player> \<amount> | mccredits.pay                                               | Transfer credits to another player.                |
| /mccredits shop \[player]          | <p>mccredits.shop (for self)</p><p>mccredits.admin.shop</p> | Open the shop menu for yourself or another player. |

## Admin Commands

| Command                                                                                                           | Permission                                     | Description                                              |
| ----------------------------------------------------------------------------------------------------------------- | ---------------------------------------------- | -------------------------------------------------------- |
| /mccredits get \[player]                                                                                          | mccredits.admin.get mccredits.get.self         | View your own or another player’s credit balance.        |
| /mccredits reload                                                                                                 | mccredits.admin.reload                         | Reload the plugin configuration.                         |
| /mccredits help                                                                                                   | mclmccredits.admin.help                        | View a list of available commands.                       |
| /mccredits give \<player> \<amount>                                                                               | mccredits.admin.give                           | *Gi*ve credit to a player.                               |
| /mccredits take \<player> \<amount>                                                                               | mccredits.admin.take                           | Remove credits from a player.                            |
| /mccredits set \<player> \<amount>                                                                                | mccredits.admin.set                            | Set a player's credits to a specific amount.             |
| /mccredits reset \<player/\**>*                                                                                   | mccredits.admin.reset mccredits.admin.resetall | Reset a player’s credits. (or all players if \* is used) |
| /mccredits purchases \[player]                                                                                    | mccredits.admin.purchases                      | View a player's purchase history.                        |
| /mccredits discount \<create/remove> \<name> \<all/category/item> \<product\_id> \<percentage/absolute> \<amount> | mccredits.admin.discount                       | Manage discounts on shop items.                          |


# Feature Help


# GUI Options

### Options for GUI Configuration:

#### Applicable to All Menus:

* `slot` (required) - **The slot of the item**
* `item` (required) - **The material of the item**
* `title` (required) - **The name of the item**
* `description` (required) - **The lore of the item**
* `amount` (optional) - **The amount of the item**
* `custommodeldata` (optional) - **The model data of the item**
* `skull_texture` (optional) - **The texture of the skull item (the item type must be PLAYER\_HEAD)**
* `skull_owner` (optional) - **The owner of the skull item (the item type must be PLAYER\_HEAD)**
* `required_permission` (optional) - **The required permission to execute the item's click commands**
* `blacklisted_permission` (optional) - **The blacklisted permission to prevent executing the item's click commands**
* `commands` (optional) - **The commands executed when the player clicks the item (if the item has a price, the commands will only be executed if the player has enough credit to purchase it)**

#### Applicable Only to Category Menus:

* `price` (required) - **The price of the item (this amount is automatically deducted when a player buys the product)**
* `confirm` (optional) - **If item purchase requires confirmation, set this option to true**
* `stock` (optional) - **The stock of the product**

### GUI Commands

* `[COMMAND]` (all GUI) - **Executes a command as the console**
* `[PLAYER]` (all GUI) - **Executes a command as the player**
* `[MESSAGE]` (all GUI) - **Sends a message to the player**
* `[SOUND]` (all GUI) - **Plays a sound for the player**
* `[OPEN-GUI]` (all GUI) - **Opens a GUI for the player**
* `[CLOSE]` (all GUI) - **Closes the GUI for the player**
* `[BACK]` (confirm GUI) - **Returns to the previous category where the confirmation menu was triggered**
* `[CONFIRM-COMMANDS]` (confirm GUI) - **Executes the original product commands**
* `[CONFIRM-RESETALL]` (reset-all-confirm GUI) - **Resets all of the player's credit balance**

### GUI Placeholders

* `PlaceholderAPI placeholders` - **The GUI supports PlaceholderAPI placeholders**
* `%price%` - **Displays the price of the product**
* `%stock%` - **Displays the stock of the product**


# Supported Plugins

{% content-ref url="/pages/ChHkH2cwfnmoLasQtpmO" %}
[PlaceholderAPI](/premium-products/credits/supported-plugins/placeholderapi)
{% endcontent-ref %}


# PlaceholderAPI

Current active placeholders for the plugin

## Placeholders

| Placeholder                     | Output                           |
| ------------------------------- | -------------------------------- |
| %mccredits\_credits%            | Player's balance.                |
| %mccredits\_credits\_formatted% | Player's formatted balance.      |
| %mccredits\_top\_1%             | The balance of the top 1 player. |
| %mccredits\_top\_1\_name%       | The name of the top 1 player.    |


# Developer API

### 1) Add the Dependency

Don't forget to change always the version!

<div align="left"><figure><img src="https://img.shields.io/maven-metadata/v.svg?label=CreditsAPI&#x26;metadataUrl=https://repo.mongenscave.com/releases/com/mongenscave/mc-CreditsAPI/maven-metadata.xml" alt=""><figcaption></figcaption></figure></div>

{% tabs %}
{% tab title="Maven" %}

<pre class="language-xml" data-full-width="true"><code class="lang-xml"><strong>&#x3C;repository>
</strong>  &#x3C;id>MonGens-Cave&#x3C;/id>
  &#x3C;url>https://repo.mongenscave.com/releases&#x3C;repository>&#x3C;/url>
&#x3C;/repository>

&#x3C;dependency>
  &#x3C;groupId>com.mongenscave&#x3C;/groupId>
  &#x3C;artifactId>mc-CreditsAPI&#x3C;/artifactId>
  &#x3C;version>[VERSION]&#x3C;/version>
&#x3C;/dependency>
</code></pre>

{% endtab %}

{% tab title="Gradle" %}

```groovy
maven { url "https://repo.mongenscave.com/releases" }

implementation "com.mongenscave:mc-CreditsAPI:[VERSION]"
```

{% endtab %}
{% endtabs %}

### 2) Add mc-Credits to plugin.yml

{% tabs %}
{% tab title="as depend" %}

```yaml
depend:
  - mc-Credits
```

{% endtab %}

{% tab title="as softdepend" %}

```yaml
softdepend:
  - mc-Credits
```

{% endtab %}
{% endtabs %}

### 3) Example how to use the CreditsAPI

As an example, add Credit to a player.

```java
public class CreditExemple {
   public void giveCredit(Player player, int amount){
       CreditUtil.addCredits(player, amount);
   }
}
```

| Event             | Description                                               |
| ----------------- | --------------------------------------------------------- |
| CreditChangeEvent | Triggered when a player's credit balance is modified.     |
| PlayerBoughtEvent | Triggered when a player buys anything in the credit shop. |


# mc-Homes

Elevate your server with our innovative Homes plugin!

<figure><img src="/files/hItS8K9jVrmx4EG36Jft" alt=""><figcaption></figcaption></figure>

### Plugin Features

* Fully Customizable messages
* MySQL and H2 support
* Multi-server Support
* Highly Optimized
* Hex Color Support
* Fully customizable GUIs
* Custom-Model-Data Support in GUis
* Multiple item slots Support in GUIs
* Convert data's from another plugin
* Safe teleport locations
* Home Share System
* Banned Words in Home names
* Teleport Delay, titles, messages, actionbar messages

{% hint style="info" %}
Whatever complex request you have for the plugin, we will solve it for you!
{% endhint %}


# Plugin FAQ

Here are the features of the plugin, along with answers to frequently asked questions

### Why should you use mc-Homes?

* **mc-Homes** is a lightweight and fast plugin designed for seamless home management. It handles players’ homes with high efficiency and stability, even when individual players or the entire server have a large number of saved homes. \
  \
  The plugin is fully **GUI-based**, allowing players to teleport to their homes through an intuitive interface that supports pagination. Additionally, players can **share their homes** with friends, making it a user-friendly and social experience.

### What makes mc-Homes stand out from other home plugins?

* The plugin offers a **clean and minimal experience** from the player's perspective, as it is **entirely GUI-based**. It avoids cluttering the chat with unnecessary home messages or home lists, unlike many other plugins.<br>

  Moreover, mc-Homes is built around **slot-based limitations** instead of permission-based systems, providing a more intuitive and flexible approach to managing home limits.

### What is the slot system and how does it work?

* Instead of using permission-based limits like `homes.maxhome.10`, **mc-Homes** introduces a unique **slot-based system**. Slots define how many homes a player can use, and they are managed via commands. \
  \
  For example, you can run `/homesadmin addslot kxtsoo 10` to give a player 10 slots. Inside the GUI, the player will see **10 available home item slots** they can use to set or manage their homes. \
  \
  Slots can also be **removed** from a player, and when that happens, they will **lose access to some of their homes**, depending on how many slots remain.

## What happens if you lose a slot that had an active home on it?

* If you lose one or more home slots and any of your **active homes were placed on those lost slots**, those homes will be put into a **"suspended" state**. While suspended, the home is **inaccessible**—you won’t be able to teleport to it or manage it normally.\
  \
  However, once you **regain enough slots**, the suspended home will be **automatically restored** to its original state with full access. You can also **delete suspended homes** manually if you no longer need them.

{% hint style="success" %}
If you have any questions or need help, feel free to contact us on our [Discord server](https://dc.mongenscave.com)!
{% endhint %}


# Commands

The current commands in the plugin.

## Player Commands

| Command     | Permission                                   | Description               |
| ----------- | -------------------------------------------- | ------------------------- |
| /homes      | homes.use                                    | Open the Main Home GUI.   |
| /homes help | <p>homes.player.help<br>homes.admin.help</p> | Help for plugin commands. |

## Admin Commands

| Command                                | Permission           | Description                                 |
| -------------------------------------- | -------------------- | ------------------------------------------- |
| /homesadmin reload                     | homes.admin.reload   | Reload the plugin files.                    |
| /homesadmin addslot \<player> \<slot>  | homes.admin.addslot  | Give slot for a player.                     |
| /homesadmin takeslot \<player> \<slot> | homes.admin.takeslot | Take slot from a player.                    |
| /homesadmin setslot \<player> \<slot>  | homes.admin.setslot  | Set slot number for a player.               |
| /homesadmin \<player>                  | homes.admin.homes    | Check a player homes and manage them.       |
| /homesadmin convert \<plugin>          | homes.admin.convert  | Convert player homes from a another plugin. |


# Feature Help


# Safe Teleport

Use the plugin's safe-teleport feature for complete security!

## What does the Safe Teleport feature do?

The **Safe Teleport** feature ensures that the destination is still safe **before teleporting the player to their home**. It checks the location for potential dangers (like lava, void, or unsafe blocks) to prevent unwanted damage or death.

How the plugin reacts in these situations depends on the configured **`safe-teleport.mode`**—allowing you to choose whether the teleport is canceled, requires confirmation, or proceeds anyway.

### Type of Mode's

```yaml
  safe-teleport:
    enabled: true
    # Options: cancel, confirm, auto
    mode: "auto"
    scan-radius: 5
    check:
      air-under-player: true
      dangerous-blocks: true
      end-crystal-nearby: true
      liquid: true
      suffocation-risk: true
```

#### Mode 'cancel'

* This mode immediately blocks the teleport if the location is deemed unsafe.

#### Mode 'confirm'

* This mode opens a confirmation menu if the location is potentially dangerous, leaving it up to the player to decide whether they still want to teleport at their own risk.

#### Mode 'auto' (recommended)

* In this mode, if the location is unsafe, the plugin will attempt to find a safe spot nearby within the specified radius. If a safe location is found, the player will be teleported there; otherwise, the teleport will fail.


# Home Name

This section of the configuration controls how players can name their homes. It provides fine-grained control over name length, color codes, and content filtering using both word blacklists and regula

### Regex Filtering – How It Works & How to Customize It

Regular expressions (regex) are powerful text-matching patterns used to block unwanted home names. While they can look complicated, this section will help you understand **what the current regex does** and **how to add your own rules easily**, even without advanced knowledge.

## 🔍 What the current regex does

```yaml
regex: "(?i)(([a-zA-Z0-9.-]+)?\\.(gg|com|net|org|xyz|co|me|io|hu|uk|us|de|fr|it)(\\s|$)|f[uú][cçkq][kq])"
```

This pattern is designed to block:

1. **Domain names and server ads**\
   Examples it will block:
   * `example.com`
   * `mycoolserver.net`
   * `play.server.gg`
2. **Swear word variations**\
   Specifically obfuscated forms of the word `fuck`, like:
   * `fúck`, `fuçk`, `fuqk`, `fück`

It uses **case-insensitive matching** (`(?i)`), so it also blocks uppercase versions.

### 🧩 How to add your own regex (even if you're not a regex expert)

If you want to block something specific (e.g., names like "test123" or any word containing "hack"), you can simply extend the existing regex pattern using `|` (OR).

**Example: Block “test123” and anything starting with “hack”**

```yaml
regex: "(?i)(([a-zA-Z0-9.-]+)?\\.(gg|com|net|...)(\\s|$)|f[uú][cçkq][kq]|test123|hack[a-z]*)"
```

> 💡 `|` means OR\
> 💡 `hack[a-z]*` blocks "hack", "hacker", "hacking", etc.

### ✍️ Tips for Regex Editing

* Always escape backslashes (`\\.` instead of just `.`) in YAML.
* Wrap the entire expression in quotes (`"..."`), especially when using special characters.
* Test your regex online using tools like [regex101.com](https://regex101.com/) before adding it to your config.


# Supported Plugins

{% content-ref url="/pages/ChHkH2cwfnmoLasQtpmO" %}
[PlaceholderAPI](/premium-products/credits/supported-plugins/placeholderapi)
{% endcontent-ref %}


# PlaceholderAPI

Current active placeholders for the plugin

## Placeholders

| Placeholder                     | Output                           |
| ------------------------------- | -------------------------------- |
| %mccredits\_credits%            | Player's balance.                |
| %mccredits\_credits\_formatted% | Player's formatted balance.      |
| %mccredits\_top\_1%             | The balance of the top 1 player. |
| %mccredits\_top\_1\_name%       | The name of the top 1 player.    |


# Developer API

### 1) Add the Dependency

Don't forget to change always the version!

<div align="left"><figure><img src="https://img.shields.io/maven-metadata/v.svg?label=CreditsAPI&#x26;metadataUrl=https://repo.mongenscave.com/releases/com/mongenscave/mc-CreditsAPI/maven-metadata.xml" alt=""><figcaption></figcaption></figure></div>

{% tabs %}
{% tab title="Maven" %}

<pre class="language-xml" data-full-width="true"><code class="lang-xml"><strong>&#x3C;repository>
</strong>  &#x3C;id>MonGens-Cave&#x3C;/id>
  &#x3C;url>https://repo.mongenscave.com/releases&#x3C;repository>&#x3C;/url>
&#x3C;/repository>

&#x3C;dependency>
  &#x3C;groupId>com.mongenscave&#x3C;/groupId>
  &#x3C;artifactId>mc-CreditsAPI&#x3C;/artifactId>
  &#x3C;version>[VERSION]&#x3C;/version>
&#x3C;/dependency>
</code></pre>

{% endtab %}

{% tab title="Gradle" %}

```groovy
maven { url "https://repo.mongenscave.com/releases" }

implementation "com.mongenscave:mc-CreditsAPI:[VERSION]"
```

{% endtab %}
{% endtabs %}

### 2) Add mc-Credits to plugin.yml

{% tabs %}
{% tab title="as depend" %}

```yaml
depend:
  - mc-Credits
```

{% endtab %}

{% tab title="as softdepend" %}

```yaml
softdepend:
  - mc-Credits
```

{% endtab %}
{% endtabs %}

### 3) Example how to use the CreditsAPI

As an example, add Credit to a player.

```java
public class CreditExemple {
   public void giveCredit(Player player, int amount){
       CreditUtil.addCredits(player, amount);
   }
}
```

| Event             | Description                                               |
| ----------------- | --------------------------------------------------------- |
| CreditChangeEvent | Triggered when a player's credit balance is modified.     |
| PlayerBoughtEvent | Triggered when a player buys anything in the credit shop. |


# mc-Gifts

Make sure everyone knows what you are listening to!

## Plugin Features

* Fully Customizable messages & config
* H2 for the FAST and ASYNC solutions
* Highly optimized, thread-safe
* Hex Color support
* Custom-Model-Data support in GUIs
* Multiple item slots support in GUIs
* SmartSlotting Technology in GUIs
* 1.18-1.21.x Version support
* Toast messages
* Extra message to the player who gets gifted
* Daily limits
* Free and not free gifts, your choice!


# Plugin FAQ

Here are the features of the plugin, along with answers to frequently asked questions

## Why does our plugin stand out from the others?

The plugin is just pure speed, in the spark it doesn't even "spark" up, haha. The plugin makes sure NO gift is missing, everyone gets what they earned. Just try it out, to know what is community on a server.

## Why you should use OUR plugin?

Our plugin represents games gift mechanic. It handles the offline players, full inventories etc..

Also you can limit your players with daily limits, costs using our newest currency technology!


# Commands & Permissions

The current commands in the plugin

| Command         | Permission   | Description                      |
| --------------- | ------------ | -------------------------------- |
| /gifts (target) | gifts.use    | Sends a gift to the target.      |
| /gifts collect  | gifts.use    | Collects the uncollected gifts.  |
| /gifts random   | gifts.use    | Sends a gift to a random player. |
| /gifts reload   | gifts.reload | Reloads the plugin.              |

## Extra Permission(s)

| Permission           | Description                     |
| -------------------- | ------------------------------- |
| gifts.daily.(number) | Can set a player's daily limit. |


# Currencies

You can see some information about the currency system

You'll see a currencies.yml in the plugin's folder. In that file you see 3 parameters for a currency.

* get
* give
* take

| Parameter | What does it do?                             |
| --------- | -------------------------------------------- |
| get       | Gets the player's balance with placeholders. |
| give      | Gives the player x currency amount.          |
| take      | Takes x currency amount from the player.     |


# mc-TycoonHoe

A next-gen Tycoon Hoe plugin for ultra-fast, efficient farming!

<figure><img src="/files/c1xT5Z0rmKp2agt5uzM5" alt=""><figcaption></figcaption></figure>

***

#### Plugin Features

* High Optimized plugin, the plugin does not cause lags
* 1.18-1.21.x Version Support
* Hex Color code Support
* Folia Support
* GUI Based System
* Easy to customizable
* Supports 75+ Crop
* Hoe Skin System
* Hoe Crystal System
* Client Side Farming
* Prestige System

{% content-ref url="/pages/TjfeFIlzSReTruJvLgMs" %}
[Config Files](/premium-products/mc-tycoonhoe/config-files)
{% endcontent-ref %}


# Config Files

***

{% content-ref url="/pages/a3pxVY7VYNpW7ySak6MG" %}
[config.yml](/premium-products/mc-tycoonhoe/config-files/config.yml)
{% endcontent-ref %}


# config.yml

***

```yaml
database:
  type: "h2" # H2, MySQL

  mysql:
    host: "localhost"
    port: 3306
    database: "database"
    username: "username"
    password: "password"

  pool:
    maximumPoolSize: 10
    minimumIdle: 5
    connectionTimeout: 30000
    maxLifetime: 1800000
    idleTimeout: 600000
    setLeakDetectionThreshold: 60000
    useSSL: false

tycoon-hoe:
  material: DIAMOND_HOE
  name: "&#F59E0B&lTYCOON &#FB923C&lHOE"
  lore:
    - "&#374151&l&m────────────────────"
    - "&#9CA3AFOwner: &#F3F4F6{owner_name}"
    - "&#9CA3AFLevel: &#F59E0B{level}"
    - "&#9CA3AFPrestige: &#F59E0B{prestige}"
    - "&#9CA3AFXP: &#FDE68A{xp} &#6B7280/ &#FDE68A{xp_next}"
    - "&#9CA3AFProgress: {progress}"
    - "&#374151&l&m────────────────────"
    - "{enchants}"
    - "&#374151&l&m────────────────────"
  enchant-lore:
    header: "&#60A5FA&lENCHANTS"
    line: "&#60A5FA◆ &#93C5FD{display} &#6B7280Lvl. {level}"
    none: "&#6B7280No enchants"
    show-when-empty: true
  enchantments:
    - efficiency:5
    - unbreaking:3
  unbreakable: true
  flag:
    - HIDE_ATTRIBUTES
    - HIDE_ENCHANTS
    - HIDE_UNBREAKABLE
  custom-model-data: 12001

  protection:
    move: true
    swap-offhand: true
    # Hard drop, if its enabled the drop-confirm ignored
    drop: true
    drop-confirm:
      enabled: true
      window-ms: 3000
    pickup: false
    keep-on-death:
      enabled: true
  menu:
    # Options: RIGHT_CLICK, SHIFT_RIGHT_CLICK, LEFT_CLICK, etc.
    open-action: SHIFT_RIGHT_CLICK

formats:
  amount-format: "COMPACT"
  time-format: "CLOCK_DD_HH_MM_SS"

leveling:
  initial:
    level: 0
    xp: 0.0
    prestige: 0

  formula:
    base: 500
    max-level: 100
    expression: "({previous} * 1.15) + (550 + ({level} * 25))"

  overrides: {}

  notify:
    # {xp}, {xp_formatted}, {essence}, {essence_formatted}
    farm-actionbar: "&#A7F3D0+{xp_formatted} XP &#9CA3AF| &#38BDF8+{essence_formatted} Essence"
    actionbar: "&6Level Up &8» &e{from} &7→ &a{to} &8(+{gained})"

    execute-commands:
      - "say {player} levelled up!"

    title:
      header: "&#F59E0B&lLEVEL UP!"
      sub: "&#9CA3AF{from} &#6B7280→ &#A7F3D0{to}"
      fade-in: 10
      stay: 40
      fade-out: 10

    chat:
      - "&7You reached &6level {to}&7 on your Tycoon Hoe &8(+{gained})"

    sound:
      type: "ENTITY_PLAYER_LEVELUP"
      volume: 1.0
      pitch: 1.1

  rewards:
    "10":
      - "eco give {player} 500"

stats:
  crops:
    enabled: true
    flush-interval-seconds: 60
    max-keys-before-flush: 5000

    # e.g.: ["WHEAT","CARROTS"] if empty -> EVERYTHING
    track-only: []

condense:
  requirements:
    enabled: true
    min-hoe-level: 5
    min-prestige: 0

farm:
  trigger: WHEAT
  area:
    world: ""
    min: [0, 0, 0]
    max: [0, 0, 0]

harvest:
  require-grown: true

  # SERVER | CLIENT
  render-mode: SERVER

  growth:
    enabled: true
    ticks-per-stage: "8-12"
    double-height-restore: "20"
    single-restore: "20"

  client:
    keep-final-stage: true

  drop-settings:
    straight-to-inventory: true
    drop-items-floor-if-full-inventory: false

  rules:
    # Crops
    WHEAT:
      xp: "50"
      min-level: 0
      essence: 3
      drop:
        amount: 1
        material: "WHEAT"
        name: "&#A3E635&lFresh Wheat"
        lore:
          - "&#9CA3AFHarvested with love"
          - "&#6EE7F9+Essence infused"
        enchantments:
          - "unbreaking:1"
        flag:
          - "HIDE_ENCHANTS"
        unbreakable: false
        evolution-item:
          material: "WHEAT"
          needed-amount: 5
          name: "&#A3E635&lFresh Wheat &#FBBF24&l(Baked)"
          lore:
            - "&#9CA3AFBaked to perfection"
            - "&#6EE7F9+Essence infused"
          enchantments:
            - "unbreaking:2"
          flag:
            - "HIDE_ENCHANTS"
          unbreakable: false
    CARROTS:
      xp: 50
      min-level: 1
      essence: 3
    POTATOES:
      xp: "40-70"
      min-level: 2
      essence: 3
    BEETROOTS:
      xp: 55
      min-level: 0
      essence: 3
    NETHER_WART:
      xp: "80-120"
      min-level: 4
      essence: 3
    SWEET_BERRY_BUSH:
      xp: "20-40"
      min-level: 3
    COCOA:
      xp: "70-100"
      min-level: 3
    TORCHFLOWER_CROP:
      xp: 45
      min-level: 1

    # Sugar cane
    SUGAR_CANE:
      xp: 15
      min-level: 2

    # Grass & ferns
    SHORT_GRASS:
      xp: 2
      min-level: 0
    TALL_GRASS:
      xp: 3
      min-level: 0
    FERN:
      xp: 5
      min-level: 0
    LARGE_FERN:
      xp: 7
      min-level: 0

    # Small flowers
    DANDELION:
      xp: 6
      min-level: 0
    POPPY:
      xp: 6
      min-level: 0
    BLUE_ORCHID:
      xp: 7
      min-level: 0
    ALLIUM:
      xp: 7
      min-level: 0
    AZURE_BLUET:
      xp: 7
      min-level: 0
    RED_TULIP:
      xp: 7
      min-level: 0
    ORANGE_TULIP:
      xp: 7
      min-level: 0
    WHITE_TULIP:
      xp: 7
      min-level: 0
    PINK_TULIP:
      xp: 7
      min-level: 0
    OXEYE_DAISY:
      xp: 7
      min-level: 0
    CORNFLOWER:
      xp: 7
      min-level: 0
    LILY_OF_THE_VALLEY:
      xp: 8
      min-level: 0
    WITHER_ROSE:
      xp: 12
      min-level: 3
    TORCHFLOWER:
      xp: 10
      min-level: 1

    # Tall flowers (double-height, top-only)
    SUNFLOWER:
      xp: 10
      min-level: 0
    LILAC:
      xp: 10
      min-level: 0
    ROSE_BUSH:
      xp: 12
      min-level: 0
    PEONY:
      xp: 10
      min-level: 0
    PITCHER_PLANT:
      xp: 14
      min-level: 1

    # Saplings
    OAK_SAPLING:
      xp: 5
      min-level: 0
    SPRUCE_SAPLING:
      xp: 5
      min-level: 0
    BIRCH_SAPLING:
      xp: 5
      min-level: 0
    JUNGLE_SAPLING:
      xp: 5
      min-level: 0
    ACACIA_SAPLING:
      xp: 5
      min-level: 0
    DARK_OAK_SAPLING:
      xp: 5
      min-level: 0
    PALE_OAK_SAPLING:
      xp: 6
      min-level: 0
    CHERRY_SAPLING:
      xp: 5
      min-level: 0

    # Corals
    TUBE_CORAL:
      xp: 8
      min-level: 1
    BRAIN_CORAL:
      xp: 8
      min-level: 1
    BUBBLE_CORAL:
      xp: 8
      min-level: 1
    FIRE_CORAL:
      xp: 8
      min-level: 1
    HORN_CORAL:
      xp: 8
      min-level: 1
    TUBE_CORAL_FAN:
      xp: 10
      min-level: 2
    BRAIN_CORAL_FAN:
      xp: 10
      min-level: 2
    BUBBLE_CORAL_FAN:
      xp: 10
      min-level: 2
    FIRE_CORAL_FAN:
      xp: 10
      min-level: 2
    HORN_CORAL_FAN:
      xp: 10
      min-level: 2

placeholders:
  number-format:
    xp-decimals: 1

  progress:
    length: 20
    filled: "■"
    empty: "□"
    filled-color: "&#FACC15"
    empty-color: "&#374151"

  crystal-progress:
    length: 10
    filled: "■"
    empty: "□"
    filled-color: "&#22C55E"
    empty-color: "&#6B7280"

version: '1'
```


# bosses.yml

***

```yaml
visual:
  spawn-location:
    world: "world"
    x: 0.5
    y: 100.0
    z: 0.5
    yaw: 0.0
    pitch: 0.0
  height-offset: 0.0
  armorstand:
    marker: true
    small: false
    no-gravity: true

bosses:
  CARROT_KING:
    name: Carrot King
    max-hp: 2500
    timeout: "1h"

    visual:
      model-id: "carrot_king"

    damage:
      # Every crop
      default: 2
      # Override
      overrides:
        CARROTS: 3
        WHEAT: 1
    bossbar:
      enabled: true
      title: "&#F59E0B&l{boss_name} &#6B7280- &#FFFFFF{hp}&#6B7280/&#FFFFFF{max} &#A1A1AA(&#FDE68A{percent}%&#A1A1AA)"
      # RED, BLUE, GREEN, YELLOW, PURPLE, PINK, WHITE
      color: RED
      # SOLID, SEGMENTED_6, SEGMENTED_10, SEGMENTED_12, SEGMENTED_20
      style: SEGMENTED_20
      update-interval: 5
    start-broadcast:
      - ""
      - "&#374151&l&m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
      - "&#E7AA66🔥 &#E7AA66&lC&#EDB06C&la&#F2B571&lr&#F8BB77&lr&#F4B773&lo&#F0B36F&lt &#E7AA66&lK&#E7AA66&li&#E7AA66&ln&#E7AA66&lg &r&#E7AA66🔥"
      - "&#9CA3AFDefeat the boss and get rewards!"
      - ""
      - "&#8A4343❤ Boss HP: &#FFFFFF{hp} &#6B7280/ &#FFFFFF{max}"
      - "&#A78BFA⌛ &#C4B5FDEvent ends in &#FFFFFF{time}"
      - ""
      - "&#10B981Break crops to deal damage and defeat the boss!"
      - "&#374151&l&m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
      - ""
    end-broadcast:
      limit: 3
      header:
        - ""
        - "&#374151&l&m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
        - "&#E7AA66🔥 &#E7AA66&lC&#EDB06C&la&#F2B571&lr&#F8BB77&lr&#F4B773&lo&#F0B36F&lt &#E7AA66&lK&#E7AA66&li&#E7AA66&ln&#E7AA66&lg &r&#E7AA66🔥"
        - "&#9CA3AFI may have fallen today, but I am still among you."
        - ""
      ranks:
        "1":
          - "&#D0B467① &#F6DE9C{player} &7- &#FAEABE{damage} ⚡ &#9CA3AF({dmg_ratio}%)"
        "2":
          - "&#C0C0C0② &#E5E4E2{player} &7- &#D1D5DB{damage} ⚡ &#9CA3AF({dmg_ratio}%)"
        "3":
          - "&#CD7F32③ &#E3B778{player} &7- &#F0C987{damage} ⚡ &#9CA3AF({dmg_ratio}%)"
        default:
          - "&#94A3B8#{rank} &#FFFFFF{player} &#6B7280- &#FFFFFF{damage}"
      footer:
        - ""
        - "&#10B981Keep farming to improve your rank next time!"
        - "&#374151&l&m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
        - ""
      personal:
        - ""
        - "&#9CA3AFYour result vs &#F6DE9C{boss_name}"
        - "&#D1D5DB• &#F3F4F6Damage: &#FFFFFF{damage} &#9CA3AF( {dmg_ratio}% )"
        - "&#D1D5DB• &#F3F4F6Rank: &#FFFFFF{rank}"
        - ""
    rewards:
      top:
        limit: 5
        per-rank:
          "1":
            - "eco give {player} 10000"
            - "give {player} NETHERITE_INGOT 1"
          "2":
            - "eco give {player} 7500"
            - "give {player} DIAMOND 2"
          "3-5":
            - "eco give {player} 5000"
            - "give {player} GOLD_INGOT 3"
          default:
            - "eco give {player} 2000"
      participants:
        min-damage: 100
        commands:
          - eco give %player% 150

  NETHERWART_OVERLORD:
    name: Netherwart Overlord
    max-hp: 18000
    timeout: "1h"

    visual:
      model-id: "carrot_king"

    damage:
      # Every crop
      default: 2
      # Override
      overrides:
        NETHER_WART: 3
        WHEAT: 1

    bossbar:
      enabled: true
      title: "&#EF4444&l{boss_name} &#6B7280- &#FFFFFF{hp}&#6B7280/&#FFFFFF{max} &#A1A1AA(&#FDE68A{percent}%&#A1A1AA)"
      color: RED
      style: SEGMENTED_20
      update-interval: 5

    start-broadcast:
      - ""
      - "&#374151&l&m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
      - "&#DC2626🔥 &#DC2626&lN&#E2342D&le&#E94434&lt&#EF533B&lh&#F56242&le&#FB7149&lr&#FF8050&lw&#FF8F57&la&#FFA65E&lr&#FFBD65&lt &#DC2626&lO&#E2342D&lv&#E94434&le&#EF533B&lr&#F56242&ll&#FB7149&lo&#FF8050&lr&#FF8F57&ld &r&#DC2626🔥"
      - "&#9CA3AFDefeat the boss and get rewards!"
      - ""
      - "&#8A4343❤ Boss HP: &#FFFFFF{hp} &#6B7280/ &#FFFFFF{max}"
      - "&#A78BFA⌛ &#C4B5FDEvent ends in &#FFFFFF{time}"
      - ""
      - "&#10B981Break crops to deal damage and defeat the boss!"
      - "&#374151&l&m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
      - ""

    end-broadcast:
      limit: 3
      header:
        - ""
        - "&#374151&l&m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
        - "&#DC2626🔥 &#DC2626&lN&#E2342D&le&#E94434&lt&#EF533B&lh&#F56242&le&#FB7149&lr&#FF8050&lw&#FF8F57&la&#FFA65E&lr&#FFBD65&lt &#DC2626&lO&#E2342D&lv&#E94434&le&#EF533B&lr&#F56242&ll&#FB7149&lo&#FF8050&lr&#FF8F57&ld &r&#DC2626🔥"
        - "&#9CA3AFI may have fallen today, but I am still among you."
        - ""
      ranks:
        "1":
          - "&#D0B467① &#F6DE9C{player} &7- &#FAEABE{damage} ⚡ &#9CA3AF({dmg_ratio}%)"
        "2":
          - "&#C0C0C0② &#E5E4E2{player} &7- &#D1D5DB{damage} ⚡ &#9CA3AF({dmg_ratio}%)"
        "3":
          - "&#CD7F32③ &#E3B778{player} &7- &#F0C987{damage} ⚡ &#9CA3AF({dmg_ratio}%)"
        default:
          - "&#94A3B8#{rank} &#FFFFFF{player} &#6B7280- &#FFFFFF{damage}"
      footer:
        - ""
        - "&#10B981Keep farming to improve your rank next time!"
        - "&#374151&l&m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
        - ""
      personal:
        - ""
        - "&#9CA3AFYour result vs &#F6DE9C{boss_name}"
        - "&#D1D5DB• &#F3F4F6Damage: &#FFFFFF{damage} &#9CA3AF( {dmg_ratio}% )"
        - "&#D1D5DB• &#F3F4F6Rank: &#FFFFFF{rank}"
        - ""

    rewards:
      top:
        limit: 5
        per-rank:
          "1":
            - "eco give {player} 12000"
            - "give {player} NETHERITE_SCRAP 2"
          "2":
            - "eco give {player} 8500"
            - "give {player} DIAMOND 3"
          "3-5":
            - "eco give {player} 6000"
            - "give {player} GOLD_INGOT 4"
          default:
            - "eco give {player} 2500"
      participants:
        min-damage: 100
        commands:
          - "eco give {player} 250"

triggers:
  - boss-id: NETHERWART_OVERLORD
    when: every:15m
    conditions:
      - '[player>=50]'
  - boss-id: CARROT_KING
    when: every:2h
    conditions: []

version: '1'
```


# crystals.yml

***

```yaml
crystals:
  SPEED:
    item:
      material: FEATHER
      name: "&#6EE7F9&lSpeed Crystal"
      lore:
        - ''
        - "&#9CA3AFBoosts the Speed enchant"
        - "&#9CA3AFand gives bonus activation chance."
      model: 1201
    max-level: 5
    enchant-boosts:
      SPEED:
        base: 1.10
        per-level: 0.05

version: '1'
```


# enchants.yml

***

```yaml
enchants:
  SPEED:
    enabled: true
    icon: "FEATHER"
    display-name: '&#6EE7F9&lSpeed'
    description:
      - '&#9CA3AFMove faster while holding the Tycoon Hoe.'
    max-level: 5
    min-hoe-level: 1
    effect:
      amplifier-per-level: 1
      duration-ticks: 220
      ambient: true
      particles: false
      icon: false
    purchase:
      enabled: true
      base: 500
      per-level: 75
      per-level-squared: 0
      multiplier: 1.0

  HASTE:
    enabled: true
    icon: "GOLDEN_PICKAXE"
    display-name: '&#FBBF24&lHaste'
    description:
      - '&#9CA3AFMine and break blocks faster while holding the Tycoon Hoe.'
    max-level: 5
    min-hoe-level: 1
    effect:
      amplifier-per-level: 1
      duration-ticks: 220
      ambient: true
      particles: false
      icon: false
    purchase:
      enabled: true
      base: 700
      per-level: 75
      per-level-squared: 0
      multiplier: 1.0

  CROP_BOOSTER:
    enabled: true
    icon: "WHEAT"
    display-name: '&#34D399&lCrop Booster'
    description:
      - '&#9CA3AFGain extra crops when harvesting.'
      - '&#9CA3AFAdds a small yield multiplier per level.'
    max-level: 500
    min-hoe-level: 3
    multiplier:
      base: 0.0
      per-level: 0.005
      max-total: 1.5
      per-crop:
        NETHER_WART: 0.05
    rounding: 'stochastic'
    purchase:
      enabled: true
      base: 2500
      per-level: 75
      per-level-squared: 0
      multiplier: 1.0

  ESSENCE_BOOSTER:
    enabled: true
    icon: "WARPED_ROOTS"
    display-name: '&#60A5FA&lEssence Booster'
    description:
      - '&#9CA3AFGain extra Essence when harvesting crops.'
      - '&#9CA3AFAdds a small multiplier per level.'
    max-level: 1500
    min-hoe-level: 3
    multiplier:
      base: 0.0
      per-level: 0.09
      max-total: 2.0
      per-crop:
        NETHER_WART: 0.05
    rounding: 'round'
    purchase:
      enabled: true
      base: 4500
      per-level: 75
      per-level-squared: 0
      multiplier: 1.0

  XP_BOOSTER:
    enabled: true
    icon: "EXPERIENCE_BOTTLE"
    display-name: '&#A78BFA&lXP Booster'
    description:
      - '&#9CA3AFGain extra hoe XP when harvesting.'
      - '&#9CA3AFAdds a small multiplier per level.'
    max-level: 5000
    min-hoe-level: 3
    multiplier:
      base: 0.0
      per-level: 0.5
      max-total: 3.0
      per-crop:
        NETHER_WART: 0.05
    purchase:
      enabled: true
      base: 2500
      per-level: 75
      per-level-squared: 0
      multiplier: 1.0

  KEY_FINDER:
    type: COMMAND
    enabled: true
    icon: "LIME_CANDLE"
    display-name: '&#22C55E&lKey Finder'
    description:
      - '&#9CA3AFChance to find a crate key when harvesting.'
    max-level: 500
    min-hoe-level: 5
    trigger:
      chance:
        base: 0.0
        per-level: 0.002
        max: 0.20
      cooldown-ticks: 200
      crops: []
      worlds: []
    commands:
      run-as: CONSOLE
      mode: RANDOM_ONE
      list:
        - "tell {player} &aYou found {random:10-50} Rare key!; [broadcast] {player} found Rare Keys!"
        - "tell {player} &aYou found a Elite key!"
        - "tell {player} &aYou found a Mythic key!"
    purchase:
      enabled: true
      base: 1750
      per-level: 75
      per-level-squared: 0
      multiplier: 1.0

  TNT_BARRAGE:
    enabled: true
    icon: "TNT"
    display-name: '&#EF4444&lTNT Barrage'
    description:
      - '&#9CA3AFOccasionally calls down TNT around'
      - '&#9CA3AFyou and harvests crops in a radius.'
      - '&#9CA3AFActivation chance increases with level.'
    max-level: 500
    min-hoe-level: 7
    trigger:
      chance:
        base: 0.0
        per-level: 0.0001
        max: 0.05
      cooldown-ticks: 200
    visuals:
      tnt-count: 1
      fuse-ticks: 100
      spawn-height: 12
      aim-crops-only: true
    harvest:
      radius: 4.0
      per-tick: 48
    purchase:
      enabled: true
      base: 5000
      per-level: 75
      per-level-squared: 0
      multiplier: 1.0

  VIRUS:
    enabled: true
    icon: "TORCHFLOWER_SEEDS"
    display-name: '&#10B981&lVirus'
    description:
      - '&#9CA3AFOccasionally infects nearby crops'
      - '&#9CA3AFand harvests them in waves.'
      - '&#9CA3AFActivation chance increases with level.'
    max-level: 500
    min-hoe-level: 10
    trigger:
      chance:
        base: 0.0
        per-level: 0.00005
        max: 0.02
      cooldown-ticks: 200
    spread:
      radius: 6.0
      max-nodes: 40
      per-tick: 16
      max-depth: 16
      spread-chance: 0.6
      neighbor-mode: DIAGONAL
      grown-only: true
    trigger-commands-during-virus: false
    purchase:
      enabled: true
      base: 6500
      per-level: 75
      per-level-squared: 0
      multiplier: 1.0

  BAT_SWARM:
    enabled: true
    icon: "BAT_SPAWN_EGG"
    display-name: '&#888888&lBat Swarm'
    description:
      - '&#9CA3AFSpawns a swarm of bats that harvest crops along their path.'
      - '&#9CA3AFActivation chance increases with level.'
    max-level: 500
    min-hoe-level: 12
    trigger:
      chance:
        base: 0.0
        per-level: 0.00008
        max: 0.03
      cooldown-ticks: 200
    swarm:
      count: 6
      speed-blocks-per-sec: 6.0
      duration-seconds: 4
      altitude: 2.5
      spread: 3.0
      particle-interval-ticks: 2
    harvest:
      radius: 1
      per-tick: 16
    trigger-commands-during-swarm: false
    purchase:
      enabled: true
      base: 7500
      per-level: 75
      per-level-squared: 0
      multiplier: 1.0

  OVERDRIVE:
    enabled: true
    icon: "OMINOUS_BOTTLE"
    display-name: '&#F43F5E&lOverdrive'
    description:
      - '&#9CA3AFRarely triggers a short burst that boosts'
      - '&#9CA3AFcrop yield, essence, and XP.'
      - '&#9CA3AFActivation chance increases with level.'
    max-level: 500
    min-hoe-level: 15
    trigger:
      chance:
        base: 0.0
        per-level: 0.00005
        max: 0.01
      cooldown-ticks: 400
    duration-seconds: 6
    yield:
      base-plus: 0.0
      per-level-plus: 0.0008
      max-plus: 0.25
    essence:
      base-plus: 0.0
      per-level-plus: 0.0008
      max-plus: 0.25
    xp:
      base-plus: 0.0
      per-level-plus: 0.0008
      max-plus: 0.25
    refresh-mode: EXTEND
    purchase:
      enabled: true
      base: 10000
      per-level: 75
      per-level-squared: 0
      multiplier: 1.0

  RAVAGER_RUSH:
    enabled: true
    icon: "GOAT_HORN"
    display-name: '&#4B5563&lRavager Rush'
    description:
      - '&#9CA3AFSpawns a harmless ravager that charges'
      - '&#9CA3AFforward and harvests crops along its path.'
      - '&#9CA3AFActivation chance increases with level.'
    max-level: 500
    min-hoe-level: 15
    trigger:
      chance:
        base: 0.0
        per-level: 0.00005
        max: 0.01
      cooldown-ticks: 300
    rush:
      speed-blocks-per-sec: 4.0
      duration-seconds: 4
      harvest-radius: 1.5
      harvest-per-tick: 16
      particle-interval-ticks: 2
    trigger-commands-during-rush: false
    purchase:
      enabled: true
      base: 15000
      per-level: 75
      per-level-squared: 0
      multiplier: 1.0

  NUKE:
    enabled: true
    icon: "TNT_MINECART"
    display-name: '&#DC2626&lNUKE'
    description:
      - '&#9CA3AFAttempts to harvest the entire farm from your'
      - '&#9CA3AFposition falls back to a large square if needed.'
      - '&#9CA3AFRare activation with a cooldown.'
    max-level: 500
    min-hoe-level: 20
    trigger:
      chance:
        base: 0.0
        per-level: 0.00002
        max: 0.005
      cooldown-ticks: 800
    shape:
      mode: SQUARE
      per-tick: 256
      max-nodes: 225

      full-scan:
        chunk-radius: 4
        y-min: 50
        y-max: 120
        max-nodes: 3000

      square:
        radius: 7
        y-min: 50
        y-max: 120

    purchase:
      enabled: true
      base: 50000
      per-level: 75
      per-level-squared: 0
      multiplier: 1.0

  BOSS_DAMAGE:
    enabled: true
    icon: "NETHERITE_SWORD"
    display-name: '&#F97316&lBOSS DAMAGE'
    description:
      - '&#9CA3AFAdds a small damage bonus against bosses'
      - '&#9CA3AFwhile you are farming with your Tycoon Hoe.'
      - '&#9CA3AFDesigned to be weak but noticeable.'
    max-level: 500
    min-hoe-level: 30

    multiplier:
      base: 0.02
      per-level: 0.00008
      max-total: 0.15
      per-boss:
        WHEAT_BOSS: 0.01
        NETHER_BOSS: 0.02

    purchase:
      enabled: true
      base: 70000
      per-level: 85
      per-level-squared: 0
      multiplier: 1.0

  # Enchant released in the 1.5.0 version
  COMBO:
    enabled: true
    icon: "BLAZE_ROD"
    display-name: '&#00D4FF&lCombo'
    description:
      - '&#9CA3AFBuild stacks while farming to earn'
      - '&#9CA3AFa powerful temporary boost.'
      - '&#9CA3AFThe more stacks, the stronger the boost.'

    max-level: 100
    min-hoe-level: 50

    stacking-seconds: 6
    boost-seconds: 6

    stack-multiplier: 0.01
    max-multiplier: 1.0

    trigger:
      cooldown-ticks: 1200
      chance:
        base: 0.0
        per-level: 0.00003
        max: 0.003

    purchase:
      enabled: true
      base: 250000
      per-level: 500
      per-level-squared: 10
      multiplier: 1.0

    messages:
      started:
        message: "&#00D4FF⚡ Combo started! Keep farming to build stacks!"
        sound: "entity.experience_orb.pickup"
      stacking:
        title: "&#00D4FF⚡ Combo"
        subtitle: "&7Stacks: &f{stacks}"
        fade-in: 0
        stay: 10
        fade-out: 0
        sound: ""
      boost:
        title: "&#00D4FF⚡ COMBO BOOST"
        subtitle: "&7Multiplier: &fx{multiplier}"
        fade-in: 5
        stay: 40
        fade-out: 10
        message: "&#00D4FF⚡ Combo activated! Multiplier: &fx{multiplier}"
        sound: "entity.player.levelup"
      no-stacks:
        message: "&cCombo ended with no stacks."
        sound: ""

version: '1'
```


# guis.yml

***

```yaml
hoe-main:
  title: "&8         ʏᴏᴜʀ ᴛʏᴄᴏᴏɴ ʜᴏᴇ"
  size: 54
  items:
    hoe:
      slot: [20]
    decoration-hoe:
      slot: [10, 11, 12, 19, 21, 28, 29, 30]
      material: YELLOW_STAINED_GLASS_PANE
      name: '&f'

    enchants:
      slot: [22]
      material: "ENCHANTING_TABLE"
      name: "&#EF4444&lEnchants"
      lore:
        - ""
        - "&#9CA3AFOpens the &#EF4444Enchants &#9CA3AFmenu."
        - "&#9CA3AFManage and upgrade &#EF4444enchantments&#9CA3AF,"
        - "&#9CA3AFconfigure &#EF4444triggers&#9CA3AF & &#EF4444levels&#9CA3AF."
        - ""
        - "&#A7F3D0▶ Click to navigate"
    decoration-enchants:
      slot: [13, 31]
      material: RED_STAINED_GLASS_PANE
      name: '&f'

    prestige:
      slot: [23]
      material: "AMETHYST_CLUSTER"
      name: "&#C084FC&lPrestige"
      lore:
        - ''
        - "&#9CA3AFOpens the &#C084FCPrestige &#9CA3AFmenu."
        - "&#9CA3AFConvert maxed levels into &#C084FCpermanent boosts&#9CA3AF."
        - "&#9CA3AFGain &#C084FCEssence&#9CA3AF, &#C084FCCrop&#9CA3AF, &#C084FCXP&#9CA3AF & &#C084FCEnchant Activation &#9CA3AFbonuses."
        - ""
        - "&#A7F3D0▶ Click to navigate"
    decoration-prestige:
      slot: [14, 32]
      material: PURPLE_STAINED_GLASS_PANE
      name: '&f'

    crystals:
      slot: [24]
      material: "PRISMARINE_SHARD"
      name: "&#C084FC&lCrystals"
      lore:
        - ''
        - "&#9CA3AFOpens the &#C084FCPrestige &#9CA3AFmenu."
        - "&#9CA3AFConvert maxed levels into &#C084FCpermanent boosts&#9CA3AF."
        - "&#9CA3AFGain &#C084FCEssence&#9CA3AF, &#C084FCCrop&#9CA3AF, &#C084FCXP&#9CA3AF & &#C084FCEnchant Activation &#9CA3AFbonuses."
        - ""
        - "&#A7F3D0▶ Click to navigate"
    decoration-crystals:
      slot: [15, 33]
      material: CYAN_STAINED_GLASS_PANE
      name: '&f'

    skin:
      slot: [25]
      material: "LOOM"
      name: "&#8B5E3C&lSkins"
      lore:
        - ""
        - "&#9CA3AFOpens the &#8B5E3CSkins &#9CA3AFmenu."
        - "&#9CA3AFBrowse cosmetic &#8B5E3Clooks&#9CA3AF, apply &#8B5E3Cstyles&#9CA3AF,"
        - "&#9CA3AFand switch &#8B5E3Cappearances&#9CA3AF."
        - ""
        - "&#A7F3D0▶ Click to navigate"
    decoration-skin:
      slot: [16, 34]
      material: BROWN_STAINED_GLASS_PANE
      name: '&f'

    settings:
      slot: [51]
      material: "BELL"
      name: "&#FDE047&lSettings"
      lore:
        - ""
        - "&#9CA3AFOpens the &#FDE047Settings &#9CA3AFmenu."
        - "&#9CA3AFAdjust visual elements, &#FDE047notifications&#9CA3AF,"
        - "&#9CA3AFand personal &#FDE047preferences&#9CA3AF."
        - ""
        - "&#A7F3D0▶ Click to navigate"

    leaderboard:
      slot: [47]
      material: "SCAFFOLDING"
      name: "&#FDE047&lLeaderboards"
      lore:
        - ""
        - "&#9CA3AFOpens the &#FDE047Leaderboards &#9CA3AFmenu."
        - "&#9CA3AFView top &#FDE047Hoe Levels&#9CA3AF, &#FDE047Essence&#9CA3AF,"
        - "&#9CA3AFand &#FDE047Crop Stats&#9CA3AF."
        - ""
        - "&#A7F3D0▶ Click to navigate"

    close:
      slot: [49]
      material: "BARRIER"
      name: "&#EF4444▼ Close the Menu ▼"
      lore: []

    decoration-bottom:
      slot: [45, 46, 48, 50, 52, 53]
      material: GRAY_STAINED_GLASS_PANE
      name: '&f'

hoe-enchants:
  title: "&8      ᴛʏᴄᴏᴏɴ ʜᴏᴇ ᴇɴᴄʜᴀɴᴛꜱ"
  size: 54

  enchant-slots: [10,11,12,13,14,15,16,19,20,21,22,23,24,25,28,29,30,31,32,33,34]

  items:
    back:
      slot: [49]
      material: "IRON_DOOR"
      name: "&#A7F3D0▼ Back to the Main ▼"
      lore: []

    prev:
      slot: [48]
      material: "ARROW"
      name: "&#9CA3AF◀ Previous Page"
      lore: []

    forward:
      slot: [50]
      material: "ARROW"
      name: "&#9CA3AFNext Page ▶"
      lore: []

    decoration-bottom:
      slot: [45, 46, 47, 51, 52, 53]
      material: GRAY_STAINED_GLASS_PANE
      name: '&f'

  template:
    material: "ENCHANTED_BOOK"
    name: "{enchant_display} &#9CA3AFLv. &#FDE047{enchant_level}&#9CA3AF/&#FDE047{enchant_max}"
    lore:
      - ""
      - "&#9CA3AF{description}"
      - ""
      - "&#A3A3A3Requires hoe level: &#F59E0B{min_hoe_level}"
      - ""
      - " &#FDE68A→ &#9CA3AF[Left] &fAdd +1&#9CA3AF: &#38BDF8{cost_plus_1} essence"
      - " &#FDE68A→ &#9CA3AF[Right] &fAdd +10&#9CA3AF: &#38BDF8{cost_plus_10} essence"
      - " &#FDE68A→ &#9CA3AF[Middle] &fAdd +100&#9CA3AF: &#38BDF8{cost_plus_100} essence"
      - ""
      - "&#FDE047 ♦ &fMax Affordable Levels: &#FDE047{max_affordable}"
      - "&#38BDF8 ♦ &#9CA3AF[Q-Key] &fCost For Max: &#38BDF8{cost_affordable} essence"
      - ""

hoe-prestige:
  title: "&8      ᴛʏᴄᴏᴏɴ ʜᴏᴇ ᴘʀᴇꜱᴛɪɢᴇ"
  size: 36

  items:
    back:
      slot: [31]
      material: "IRON_DOOR"
      name: "&#A7F3D0▼ Back to the Main ▼"
      lore: []

    prestige:
      slot: [13]
      material: "AMETHYST_CLUSTER"
      name: "&#D8B4FE&lPrestige"
      lore:
        - ""
        - "&#9CA3AFCurrent: &#FDE047P{prestige} &#9CA3AF→ &#A78BFAP{prestige_next}"
        - ""
        - "&#9CA3AFRequirement: Hoe Level &#FDE047{required_level}"
        - "&#9CA3AFYour hoe level: &#FDE047{level}"
        - ""
        - "&#9CA3AFBoosts after prestige"
        - "&#93C5FDXP: &#FDE047{xp_plus_now} &#9CA3AF→ &#FDE047{xp_plus_next}"
        - "&#93C5FDEssence: &#FDE047{essence_plus_now} &#9CA3AF→ &#FDE047{essence_plus_next}"
        - "&#93C5FDCrops: &#FDE047{crop_plus_now} &#9CA3AF→ &#FDE047{crop_plus_next}"
        - ""
        - "{can_prestige_msg}"
        - ""
        - "&#A7F3D0▶ Click to prestige"

    decoration-prestige:
      slot: [12, 14]
      material: PURPLE_STAINED_GLASS_PANE
      name: '&f'
    decoration-bottom:
      slot: [27, 28, 29, 30, 32, 33, 34, 35]
      material: GRAY_STAINED_GLASS_PANE
      name: '&f'

hoe-leaderboard:
  title: "&8       ᴛʏᴄᴏᴏɴ ʟᴇᴀᴅᴇʀʙᴏᴀʀᴅ"
  size: 54

  player-slots: [10,11,12,13,14,15,16,19,20,21,22,23,24,25,28,29,30,31,32,33,34]

  modes:
    CROPS:
      display: "&#A7F3D0Crops"
      metric: "Crops Broken"
    ESSENCE:
      display: "&#FDE68AEssence"
      metric: "Essence"
    HOE_LEVEL:
      display: "&#60A5FAHoe Level"
      metric: "Hoe Level"
    PRESTIGE:
      display: "&#F59E0BPrestige"
      metric: "Prestige"

  items:
    back:
      slot: [45]
      material: "CHAIN"
      name: "&#FCA5A5▼ Back to the Main ▼"
      lore: []

    prev:
      slot: [48]
      material: "ARROW"
      name: "&#A7F3D0← Previous Page"
      lore: []

    forward:
      slot: [50]
      material: "ARROW"
      name: "&#A7F3D0Next Page →"
      lore: []

    mode:
      slot: [49]
      material: "COMPARATOR"
      name: "&#FDE68ASort: &#FFFFFF{mode}"
      lore:
        - ""
        - "&#A7F3D0▶ Click to switch"

    decoration-bottom:
      slot: [46, 47, 51, 52, 53]
      material: GRAY_STAINED_GLASS_PANE
      name: '&f'

  player-template:
    material: "PLAYER_HEAD"
    name: "&#FDE047#{rank} &#F3F4F6{player}"
    lore:
      - ""
      - "&#9CA3AF{metric}: &#FDE68A{value_formatted}"
      - ""

hoe-skins:
  title: "&8         ᴛʏᴄᴏᴏɴ ʜᴏᴇ ꜱᴋɪɴꜱ"
  size: 54

  template:
    material: PAPER
    name: "{display-name}"
    lore:
      - ""
      - "{lore}"
      - ""
      - "&#A7F3D0▶ Click to apply"

  items:
    back:
      slot: [45]
      material: "IRON_DOOR"
      name: "&#A7F3D0▼ Back to the Main ▼"
      lore: []

    prev:
      slot: [48]
      material: "ARROW"
      name: "&#9CA3AF◀ Previous Page"
      lore: []

    forward:
      slot: [50]
      material: "ARROW"
      name: "&#9CA3AFNext Page ▶"
      lore: []

    unapply:
      slot: [49]
      material: "END_CRYSTAL"
      name: "&#FCA5A5&lUnapply Skin"
      lore:
        - ""
        - "&#9CA3AFBack to the classic look."
        - "&#9CA3AFNo skin, original style."
        - ""
        - "&#A7F3D0▶ Click to unapply"

    decoration-bottom:
      slot: [46, 47, 51, 52, 53]
      material: GRAY_STAINED_GLASS_PANE
      name: "&f"

  skin-slots: [10, 11, 12, 13, 14, 15, 16, 19, 20, 21, 22, 23, 24, 25, 28, 29, 30, 31, 32, 33, 34, 37, 38, 39, 40, 41, 42, 43]

hoe-settings:
  title: "&8      ᴛʏᴄᴏᴏɴ ʜᴏᴇ ꜱᴇᴛᴛɪɴɢꜱ"
  size: 36

  items:
    back:
      slot: [31]
      material: "IRON_DOOR"
      name: "&#A7F3D0▼ Back to the Main ▼"
      lore: []

    decoration-bottom:
      slot: [27, 28, 29, 30, 32, 33, 34, 35]
      material: GRAY_STAINED_GLASS_PANE
      name: "&f"

    actionbar:
      slot: [10]
      on:
        material: LIME_CANDLE
        name: "&#34D399&lActionbar &#16A34A&lON"
        lore:
          - ""
          - "&#9CA3AFShort updates above your hotbar."
          - ""
          - "&#A7F3D0▶ Click to toggle"
      off:
        material: GRAY_CANDLE
        name: "&#34D399&lActionbar &#6B7280&lOFF"
        lore:
          - ""
          - "&#9CA3AFActionbar messages are hidden."
          - ""
          - "&#A7F3D0▶ Click to toggle"

    message:
      slot: [12]
      on:
        material: LIME_CANDLE
        name: "&#38BDF8&lChat Message &#16A34A&lON"
        lore:
          - ""
          - "&#9CA3AFDetailed info in chat."
          - ""
          - "&#A7F3D0▶ Click to toggle"
      off:
        material: GRAY_CANDLE
        name: "&#38BDF8&lChat Message &#6B7280&lOFF"
        lore:
          - ""
          - "&#9CA3AFChat notifications are hidden."
          - ""
          - "&#A7F3D0▶ Click to toggle"

    title:
      slot: [14]
      on:
        material: LIME_CANDLE
        name: "&#FDE047&lTitle &#16A34A&lON"
        lore:
          - ""
          - "&#9CA3AFBig center-screen popups."
          - ""
          - "&#A7F3D0▶ Click to toggle"
      off:
        material: GRAY_CANDLE
        name: "&#FDE047&lTitle &#6B7280&lOFF"
        lore:
          - ""
          - "&#9CA3AFTitles are hidden."
          - ""
          - "&#A7F3D0▶ Click to toggle"

    sound:
      slot: [16]
      on:
        material: LIME_CANDLE
        name: "&#C084FC&lSound &#16A34A&lON"
        lore:
          - ""
          - "&#9CA3AFAudio cues for events."
          - ""
          - "&#A7F3D0▶ Click to toggle"
      off:
        material: GRAY_CANDLE
        name: "&#C084FC&lSound &#6B7280&lOFF"
        lore:
          - ""
          - "&#9CA3AFAudio cues are muted."
          - ""
          - "&#A7F3D0▶ Click to toggle"

farm-crop:
  title: "&8          ꜰᴀʀᴍ ᴍᴀɴᴀɢᴇᴍᴇɴᴛ"
  size: 54

  content-slots: [11, 12, 13, 14, 15, 20, 21, 22, 23, 24, 29, 30, 31, 32, 33]

  crops:
    wheat:
      material: WHEAT
      apply-material: WHEAT
      prestige-require: 0
      name: "&#FCD34D&lWheat"
      lore:
        - ""
        - "&#9CA3AFExperience: &#93C5FD{exp_gain}"
        - "&#9CA3AFEssence: &#38BDF8{essence_gain}"
        - ""
        - "&fPrestige: &c{prestige_require}"
        - ""
        - "&#A7F3D0▶ Click to apply the crop"

    carrots:
      material: CARROT
      apply-material: CARROTS
      prestige-require: 2
      name: "&#FCD34D&lCarrots"
      lore:
        - ""
        - "&#9CA3AFExperience: &#93C5FD{exp_gain}"
        - "&#9CA3AFEssence: &#38BDF8{essence_gain}"
        - ""
        - "&fPrestige: &c{prestige_require}"
        - ""
        - "&#A7F3D0▶ Click to apply the crop"

    potato:
      material: POTATO
      apply-material: POTATOES
      prestige-require: 5
      name: "&#FCD34D&lPotatoes"
      lore:
        - ""
        - "&#9CA3AFExperience: &#93C5FD{exp_gain}"
        - "&#9CA3AFEssence: &#38BDF8{essence_gain}"
        - ""
        - "&fPrestige: &c{prestige_require}"
        - ""
        - "&#A7F3D0▶ Click to apply the crop"

    beetroot:
      material: BEETROOT
      apply-material: BEETROOTS
      prestige-require: 10
      name: "&#FCD34D&lBeetroot"
      lore:
        - ""
        - "&#9CA3AFExperience: &#93C5FD{exp_gain}"
        - "&#9CA3AFEssence: &#38BDF8{essence_gain}"
        - ""
        - "&fPrestige: &c{prestige_require}"
        - ""
        - "&#A7F3D0▶ Click to apply the crop"

    nether_wart:
      material: NETHER_WART
      apply-material: NETHER_WART
      prestige-require: 15
      name: "&#FCD34D&lNether Wart"
      lore:
        - ""
        - "&#9CA3AFExperience: &#93C5FD{exp_gain}"
        - "&#9CA3AFEssence: &#38BDF8{essence_gain}"
        - ""
        - "&fPrestige: &c{prestige_require}"
        - ""
        - "&#A7F3D0▶ Click to apply the crop"

    charry_sapling:
      material: SUGAR_CANE
      apply-material: SUGAR_CANE
      prestige-require: 20
      name: "&#FCD34D&lSugar Cane"
      lore:
        - ""
        - "&#9CA3AFExperience: &#93C5FD{exp_gain}"
        - "&#9CA3AFEssence: &#38BDF8{essence_gain}"
        - ""
        - "&fPrestige: &c{prestige_require}"
        - ""
        - "&#A7F3D0▶ Click to apply the crop"

    peony:
      material: PEONY
      apply-material: PEONY
      prestige-require: 30
      name: "&#FCD34D&lPeony"
      lore:
        - ""
        - "&#9CA3AFExperience: &#93C5FD{exp_gain}"
        - "&#9CA3AFEssence: &#38BDF8{essence_gain}"
        - ""
        - "&fPrestige: &c{prestige_require}"
        - ""
        - "&#A7F3D0▶ Click to apply the crop"

    rose_bush:
      material: ROSE_BUSH
      apply-material: ROSE_BUSH
      prestige-require: 40
      name: "&#FCD34D&lMelon"
      lore:
        - ""
        - "&#9CA3AFExperience: &#93C5FD{exp_gain}"
        - "&#9CA3AFEssence: &#38BDF8{essence_gain}"
        - ""
        - "&fPrestige: &c{prestige_require}"
        - ""
        - "&#A7F3D0▶ Click to apply the crop"

    lilac:
      material: LILAC
      apply-material: LILAC
      prestige-require: 50
      name: "&#FCD34D&lLilac"
      lore:
        - ""
        - "&#9CA3AFExperience: &#93C5FD{exp_gain}"
        - "&#9CA3AFEssence: &#38BDF8{essence_gain}"
        - ""
        - "&fPrestige: &c{prestige_require}"
        - ""
        - "&#A7F3D0▶ Click to apply the crop"

    pitcher_plant:
      material: PITCHER_PLANT
      apply-material: PITCHER_PLANT
      prestige-require: 55
      name: "&#FCD34D&lPitcher Plant"
      lore:
        - ""
        - "&#9CA3AFExperience: &#93C5FD{exp_gain}"
        - "&#9CA3AFEssence: &#38BDF8{essence_gain}"
        - ""
        - "&fPrestige: &c{prestige_require}"
        - ""
        - "&#A7F3D0▶ Click to apply the crop"

    bubble_coral:
      material: BUBBLE_CORAL
      apply-material: BUBBLE_CORAL
      prestige-require: 60
      name: "&#FCD34D&lBubble Coral"
      lore:
        - ""
        - "&#9CA3AFExperience: &#93C5FD{exp_gain}"
        - "&#9CA3AFEssence: &#38BDF8{essence_gain}"
        - ""
        - "&fPrestige: &c{prestige_require}"
        - ""
        - "&#A7F3D0▶ Click to apply the crop"

    tube_coral:
      material: TUBE_CORAL
      apply-material: TUBE_CORAL
      prestige-require: 65
      name: "&#FCD34D&lTube Coral"
      lore:
        - ""
        - "&#9CA3AFExperience: &#93C5FD{exp_gain}"
        - "&#9CA3AFEssence: &#38BDF8{essence_gain}"
        - ""
        - "&fPrestige: &c{prestige_require}"
        - ""
        - "&#A7F3D0▶ Click to apply the crop"

    brain_coral:
      material: BRAIN_CORAL
      apply-material: BRAIN_CORAL
      prestige-require: 70
      name: "&#FCD34D&lBrain Coral"
      lore:
        - ""
        - "&#9CA3AFExperience: &#93C5FD{exp_gain}"
        - "&#9CA3AFEssence: &#38BDF8{essence_gain}"
        - ""
        - "&fPrestige: &c{prestige_require}"
        - ""
        - "&#A7F3D0▶ Click to apply the crop"

    fire_coral:
      material: FIRE_CORAL
      apply-material: FIRE_CORAL
      prestige-require: 75
      name: "&#FCD34D&lFire Coral"
      lore:
        - ""
        - "&#9CA3AFExperience: &#93C5FD{exp_gain}"
        - "&#9CA3AFEssence: &#38BDF8{essence_gain}"
        - ""
        - "&fPrestige: &c{prestige_require}"
        - ""
        - "&#A7F3D0▶ Click to apply the crop"

    horn_coral:
      material: HORN_CORAL
      apply-material: HORN_CORAL
      prestige-require: 80
      name: "&#FCD34D&lHorn Coral"
      lore:
        - ""
        - "&#9CA3AFExperience: &#93C5FD{exp_gain}"
        - "&#9CA3AFEssence: &#38BDF8{essence_gain}"
        - ""
        - "&fPrestige: &c{prestige_require}"
        - ""
        - "&#A7F3D0▶ Click to apply the crop"

    short_dry_grass:
      material: SHORT_DRY_GRASS
      apply-material: SHORT_DRY_GRASS
      prestige-require: 90
      name: "&#FCD34D&lShort Dry Grass"
      lore:
        - ""
        - "&#9CA3AFExperience: &#93C5FD{exp_gain}"
        - "&#9CA3AFEssence: &#38BDF8{essence_gain}"
        - ""
        - "&fPrestige: &c{prestige_require}"
        - ""
        - "&#A7F3D0▶ Click to apply the crop"

    dead_bush:
      material: DEAD_BUSH
      apply-material: DEAD_BUSH
      prestige-require: 95
      name: "&#FCD34D&lDead Bush"
      lore:
        - ""
        - "&#9CA3AFExperience: &#93C5FD{exp_gain}"
        - "&#9CA3AFEssence: &#38BDF8{essence_gain}"
        - ""
        - "&fPrestige: &c{prestige_require}"
        - ""
        - "&#A7F3D0▶ Click to apply the crop"

    cactus_flower:
      material: CACTUS_FLOWER
      apply-material: CACTUS_FLOWER
      prestige-require: 105
      name: "&#FCD34D&lCactus Flower"
      lore:
        - ""
        - "&#9CA3AFExperience: &#93C5FD{exp_gain}"
        - "&#9CA3AFEssence: &#38BDF8{essence_gain}"
        - ""
        - "&fPrestige: &c{prestige_require}"
        - ""
        - "&#A7F3D0▶ Click to apply the crop"

    firefly_bush:
      material: FIREFLY_BUSH
      apply-material: FIREFLY_BUSH
      prestige-require: 120
      name: "&#FCD34D&lFirefly Bush"
      lore:
        - ""
        - "&#9CA3AFExperience: &#93C5FD{exp_gain}"
        - "&#9CA3AFEssence: &#38BDF8{essence_gain}"
        - ""
        - "&fPrestige: &c{prestige_require}"
        - ""
        - "&#A7F3D0▶ Click to apply the crop"

    torchflower:
      material: TORCHFLOWER
      apply-material: TORCHFLOWER
      prestige-require: 130
      name: "&#FCD34D&lTorchflower"
      lore:
        - ""
        - "&#9CA3AFExperience: &#93C5FD{exp_gain}"
        - "&#9CA3AFEssence: &#38BDF8{essence_gain}"
        - ""
        - "&fPrestige: &c{prestige_require}"
        - ""
        - "&#A7F3D0▶ Click to apply the crop"

    open_eyeblossom:
      material: OPEN_EYEBLOSSOM
      apply-material: OPEN_EYEBLOSSOM
      prestige-require: 145
      name: "&#FCD34D&lOpen Eyeblossom"
      lore:
        - ""
        - "&#9CA3AFExperience: &#93C5FD{exp_gain}"
        - "&#9CA3AFEssence: &#38BDF8{essence_gain}"
        - ""
        - "&fPrestige: &c{prestige_require}"
        - ""
        - "&#A7F3D0▶ Click to apply the crop"

    crimson_fungus:
      material: CRIMSON_FUNGUS
      apply-material: CRIMSON_FUNGUS
      prestige-require: 160
      name: "&#FCD34D&lCrimson Fungus"
      lore:
        - ""
        - "&#9CA3AFExperience: &#93C5FD{exp_gain}"
        - "&#9CA3AFEssence: &#38BDF8{essence_gain}"
        - ""
        - "&fPrestige: &c{prestige_require}"
        - ""
        - "&#A7F3D0▶ Click to apply the crop"

    warped_fungus:
      material: WARPED_FUNGUS
      apply-material: WARPED_FUNGUS
      prestige-require: 170
      name: "&#FCD34D&lWarped Fungus"
      lore:
        - ""
        - "&#9CA3AFExperience: &#93C5FD{exp_gain}"
        - "&#9CA3AFEssence: &#38BDF8{essence_gain}"
        - ""
        - "&fPrestige: &c{prestige_require}"
        - ""
        - "&#A7F3D0▶ Click to apply the crop"

    crimson_roots:
      material: CRIMSON_ROOTS
      apply-material: CRIMSON_ROOTS
      prestige-require: 180
      name: "&#FCD34D&lCrimson Roots"
      lore:
        - ""
        - "&#9CA3AFExperience: &#93C5FD{exp_gain}"
        - "&#9CA3AFEssence: &#38BDF8{essence_gain}"
        - ""
        - "&fPrestige: &c{prestige_require}"
        - ""
        - "&#A7F3D0▶ Click to apply the crop"

    warped_roots:
      material: WARPED_ROOTS
      apply-material: WARPED_ROOTS
      prestige-require: 200
      name: "&#FCD34D&lWarped Roots"
      lore:
        - ""
        - "&#9CA3AFExperience: &#93C5FD{exp_gain}"
        - "&#9CA3AFEssence: &#38BDF8{essence_gain}"
        - ""
        - "&fPrestige: &c{prestige_require}"
        - ""
        - "&#A7F3D0▶ Click to apply the crop"

  items:
    prev:
      slot: [47]
      material: ARROW
      name: "&#9CA3AF◀ Previous Page"

    next:
      slot: [51]
      material: ARROW
      name: "&#9CA3AFNext Page ▶"

    visibility-settings:
      slot: [49]
      material: CAULDRON
      name: "&#FDE047&lVisibility Management"
      lore:
        - ""
        - "&#9CA3AFControl who you see on your own farm!"
        - ""
        - "&#A7F3D0▶ Click to navigate"

    decoration:
      slot: [45, 46, 48, 50, 52, 53]
      material: GRAY_STAINED_GLASS_PANE
      name: " "

farm-visibility:
  title: "&8    ꜰᴀʀᴍ ᴠɪꜱɪʙɪʟɪᴛʏ ꜱᴇᴛᴛɪɴɢꜱ"
  size: 36

  items:
    everyone:
      slot: [10]
      active:
        material: LIME_CANDLE
        name: "&#16A34AEveryone"
        lore:
          - ""
          - "&#9CA3AFYou can see all players"
          - "&#9CA3AFin the farm area."
          - ""
          - "&#A7F3D0▶ Click to deactivate"
      inactive:
        material: GRAY_CANDLE
        name: "&#6B7280Everyone"
        lore:
          - ""
          - "&#9CA3AFYou can see all players"
          - "&#9CA3AFin the farm area."
          - ""
          - "&#A7F3D0▶ Click to activate"

    random10:
      slot: [12]
      active:
        material: LIME_CANDLE
        name: "&#16A34ARandom 10"
        lore:
          - ""
          - "&#9CA3AFYou will always see only 10 random"
          - "&#9CA3AFplayers in the farm area."
          - ""
          - "&#A7F3D0▶ Click to deactivate"
      inactive:
        material: GRAY_CANDLE
        name: "&#6B7280Random 10"
        lore:
          - ""
          - "&#9CA3AFYou will always see only 10 random"
          - "&#9CA3AFplayers in the farm area."
          - ""
          - "&#A7F3D0▶ Click to activate"

    friends:
      slot: [14]
      active:
        material: LIME_CANDLE
        name: "&#16A34AFriends"
        lore:
          - ""
          - "&#9CA3AFYou can only see your friends"
          - "&#9CA3AFin the farm area!"
          - ""
          - "&#A7F3D0▶ Click to deactivate"
      inactive:
        material: GRAY_CANDLE
        name: "&#6B7280Friends"
        lore:
          - ""
          - "&#9CA3AFYou can only see your friends"
          - "&#9CA3AFin the farm area!"
          - ""
          - "&#A7F3D0▶ Click to activate"

    private:
      slot: [16]
      active:
        material: LIME_CANDLE
        name: "&#16A34APrivate"
        lore:
          - ""
          - "&#9CA3AFYou won't see anyone"
          - "&#9CA3AFin the farm area."
          - ""
          - "&#A7F3D0▶ Click to deactivate"
      inactive:
        material: GRAY_CANDLE
        name: "&#6B7280Private"
        lore:
          - ""
          - "&#9CA3AFYou won't see anyone"
          - "&#9CA3AFin the farm area."
          - ""
          - "&#A7F3D0▶ Click to activate"

    back:
      slot: [31]
      material: BARRIER
      name: "&#A7F3D0▼ Back to the Farm Menu ▼"

    decoration:
      slot: [27, 28, 29, 30, 32, 33, 34, 35]
      material: GRAY_STAINED_GLASS_PANE
      name: " "

hoe-crystals:
  title: "&8      ᴛʏᴄᴏᴏɴ ʜᴏᴇ ᴄʀʏꜱᴛᴀʟꜱ"
  size: 36

  max-slots-per-player: 7
  crystal-slots: [10,11,12,13,14,15,16,19,20,21,22,23,24,25]

  items:
    back:
      slot: [31]
      material: BARRIER
      name: "&#A7F3D0▼ Back to the Farm Menu ▼"

    empty:
      material: CONDUIT
      name: "&7Empty Slot"
      lore:
        - "&8Click with a crystal"

    locked:
      material: HEAVY_CORE
      name: "&cLocked Slot"
      lore:
        - "&7You cannot use more crystals."
        - "&7Upgrade your crystal capacity!"

    template:
      material: PAPER
      name: "{crystal_display}"
      lore:
        - ''
        - '&#9CA3AFCrystals boost the specific'
        - '&#9CA3AFenchant and gives extra bonuses.'
        - ''
        - ' &#6E73BC◆ &fCrystal Level: &#6E73BCLvl. {crystal_level}'
        - " &#BA7D61◆ &fDurability: &#BA7D61{durability}&8/&#975B3F{max_durability}"
        - "    &8› &8[{durability_bar}&8]"
        - ""
        - " &#A4E079◆ &fEnchant: &#A4E079{enchant}"
        - " &#79E0C7◆ &fBoost: &#79E0C7{boost}"
        - ""
        - "&#A7F3D0▶ Click to pick up the Crystal"

    decoration:
      slot: [27, 28, 29, 30, 32, 33, 34, 35]
      material: GRAY_STAINED_GLASS_PANE
      name: " "

version: '1'
```


# hooks.yml

***

```yaml
hooks:
  friends:
    provider: "McFriends"

  PlaceholderAPI:
    enabled: true

    placeholders:
      empty: "---"
      player-profile-refresh: 10
      leaderboard-refresh: 180

  McItemStorage:
    enabled: false
  McFriends:
    enabled: false
  McTycoonPet:
    enabled: false
  McPowerUp:
    enabled: false
  BattlePass:
    enabled: false
  AxBoosters:
    enabled: false
  Nexo:
    enabled: false

  currency:
    Vault:
      enabled: true
      display-name: "Money"

version: '2'
```


# messages.yml

***

```yaml
prefix: "&#6ECA9D[TycoonHoe]"

messages:
  no-permission: "%prefix% &#EF4444You don't have permission."
  player-required: "%prefix% &#EF4444This command can only be used by a player."
  player-not-found: "%prefix% &#EF4444Player not found: &#FDE68A{target}"

  hoe:
    too-low-level-actionbar: "&#EF4444&lNOT ENOUGH LEVEL! &#F87171({level} &#9CA3AF/ &#EF4444{required}) &#9CA3AF→ &#EF4444{material}"
    confirm-drop-hoe: "&#EF4444&lCONFIRM DROP &#9CA3AF→ Press &#FDE68AQ&#9CA3AF again in &#FDE68A{seconds}s &#9CA3AFto drop your hoe."
    missing-id: "%prefix% &#EF4444Missing Hoe ID."
    attributes-load-failed: "%prefix% &#EF4444Failed to load hoe attributes."

    give:
      self: "%prefix% &#A7F3D0You received a &#FDE047Tycoon Hoe&#A7F3D0."
      other:
        sender: "%prefix% &#A7F3D0Gave a &#FDE047Tycoon Hoe &#A7F3Dto &#93C5FD{target}"
        target: "%prefix% &#A7F3D0You received a &#FDE047Tycoon Hoe &#A7F3D0from &#93C5FD{sender}"

  harvest:
    inventory-full-title:
      header: "&#F87171Inventory Full!"
      sub: "&#9CA3AFItems dropped on the ground."
      fade-in: 10
      stay: 40
      fade-out: 10
      sound: "minecraft:entity.allay.hurt"

  essence:
    balance-self: "%prefix% &#9CA3AFEssence Balance: &#38BDF8{amount} essence"
    balance-other: "%prefix% &#9CA3AFEssence Balance for {target}: &#38BDF8{amount} essence"

    pay-sent: "%prefix% &#9CA3AFSent &#38BDF8{amount} essence &#9CA3AFto &#FDE68A{target}"
    pay-received: "%prefix% &#9CA3AFYou got &#38BDF8{amount} essence &#9CA3AFfrom &#FDE68A{sender}"
    pay-self: "%prefix% &#EF4444You cannot pay yourself."
    pay-not-enough: "%prefix% &#EF4444Not enough Essence! &#9CA3AF(Need {amount})"

    give: "%prefix% &#9CA3AFGave &#38BDF8{amount} essence &#9CA3AFto &#FDE68A{target} &#9CA3AF(new: &#38BDF8{balance} essence&#9CA3AF)"
    give-other: "%prefix% &#9CA3AFYou received &#38BDF8{amount} essence &#9CA3AFfrom &#FDE68A{sender} &#9CA3AF(new: &#38BDF8{balance} essence&#9CA3AF)"
    take: "%prefix% &#9CA3AFTook &#38BDF8{amount} essence &#9CA3AFfrom &#FDE68A{target} &#9CA3AF(new: &#38BDF8{balance} essence&#9CA3AF)"
    take-fail: "%prefix% &#EF4444{target} does not have {amount} essence."
    set: "%prefix% &#9CA3AFSet &#FDE68A{target} &#9CA3AFto &#38BDF8{amount} essence&#9CA3AF."
    error: "%prefix% &#EF4444An error occurred. Try again."

  enchant:
    not-hoe: "%prefix% &#FCA5A5&lThis is not a Tycoon Hoe."
    hoe-not-found: "%prefix% &#EF4444Hoe item not found in your inventory!"
    unknown: "%prefix% &#FCA5A5&lUnknown enchant: &#F87171{id}"
    level-invalid: "%prefix% &#FCA5A5&lInvalid level: &#F87171{level} &#9CA3AF(max &#FCA5A5{max}&#9CA3AF)"
    set: "%prefix% &#6EE7F9&lEnchant set: &#93C5FD{id} &#9CA3AF→ &#A7F3D0level &#E5E7EB{level}"
    set-other: "%prefix% &#6EE7F9&lEnchant set for &#93C5FD{target}&#9CA3AF: &#A7F3D0{id} &#9CA3AF→ &#E5E7EBlevel {level}"
    no-permission: "%prefix% &#FCA5A5You don't have permission."

    purchase:
      disabled: "%prefix% &#EF4444Enchant purchasing is disabled."
      not-available: "%prefix% &#EF4444This enchant is not available."
      min-hoe-level: "%prefix% &#EF4444Your hoe level is too low for this enchant."
      max-level: "%prefix% &#F59E0BEnchant is already at max level."
      not-enough: "%prefix% &#EF4444Not enough Essence."
      success: "%prefix% &#A7F3D0Upgraded &#FDE047{enchant} &#9CA3AFfrom &#FDE047Level {level_before} &#9CA3AFto &#A7F3D0Level {level_after} &#9CA3AFfor &#FDE68A{cost} essence"

    enchant-activation:
      - "{enchant_displayname} &7activated!"
      - "&a+{essence} essence &7| &b+{xp} XP"

  prestige:
    hoe-not-found: "%prefix% &#EF4444Hoe item not found in your inventory!"
    maxed: "%prefix% &#F59E0BYou are already at max Prestige."
    no-requirement: "%prefix% &#EF4444No requirement defined for the next Prestige."
    level-required: "%prefix% &#EF4444You must reach level &#FDE047{required} &#EF4444to prestige."
    success: "%prefix% &#A7F3D0Prestiged! &#9CA3AFNew prestige: &#FDE047{new_prestige}"
    failed: "%prefix% &#EF4444Prestige failed. Requirements not met."
    currency-required: "%prefix% &#EF4444Not enough currency! &#9CA3AFRequired: &#FDE047{amount} &#9CA3AF({currency})"
    currency-failed: "%prefix% &#EF4444Could not take required currency. Try again."

    can:
      max-reached: "&#F59E0BMax Prestige reached."
      ready: "&#A7F3D0Ready to Prestige!"
      required: "&#EF4444Reach level &#FDE047{required} &#EF4444to prestige."

  condense:
    nothing: "%prefix% &#EF4444Nothing to condense."
    success:
      - "%prefix% &#A7F3D0Condense complete."
      - "&#9CA3AFTotal crafted: &#E5E7EB{total}"
    no-requirements:
      - "%prefix% &#A7F3D0Condense failed."
      - " &8→ &fRequired: &#3DA963[&#55FC8F{level}&#3DA963] &#55FC8FHoe Level"
      - " &8→ &fRequired: &#3DA963[&#55FC8F{prestige}&#3DA963] &#55FC8FPrestige"

  crystal:
    no-available-slot: "%prefix% &cYou don't have more free crystal slot.."

  farm:
    pos1-set: "%prefix% &#A7F3D0Position 1 saved."
    pos2-set: "%prefix% &#A7F3D0Position 2 saved."
    save-ok: "%prefix% &#A7F3D0Farm area saved to config."
    save-fail: "%prefix% &#EF4444Save failed. &#9CA3AFCheck pos1/pos2 and world."
    unknown-material: "%prefix% &#EF4444Unknown material."
    trigger-set: "%prefix% &#A7F3D0Trigger set to &#FDE047{material}"
    crop-set-command: "%prefix% &#A7F3D0Personal farm crop set to &#FDE047{material} &#A7F3D0for &#93C5FD{player}"
    info: "%prefix% &#9CA3AFArea: &#FDE047{area} &#9CA3AF| trigger: &#FDE047{trigger} &#9CA3AF| default-target: &#FDE047{default}"

    crop:
      not-unlocked: "%prefix% &#EF4444Not available. &#9CA3AFRequired Prestige: &#FDE047{prestige}"
      already-active: "%prefix% &#F59E0BThis crop is already active: &#E5E7EB{material}"
      set: "%prefix% &#A7F3D0Selected crop: &#FDE047{material}"

    visibility:
      already-active: "%prefix% &#F59E0BYou are already using this visibility mode: &#E5E7EB{mode}"
      set: "%prefix% &#A7F3D0Visibility mode set to &#FDE047{mode}"

  admin:
    reload:
      ok: "%prefix% &#A7F3D0Successfully reloaded the plugin."
      error: "%prefix% &#EF4444Reload failed: &#FCA5A5{error}"
    boss:
      start:
        ok: "%prefix% &#A7F3D0You successfully started the &#FDE047{id} &#A7F3D0boss!"
        fail: "%prefix% &#EF4444Failed to start boss or already active: &#FCA5A5{id}"
      end:
        ok: "%prefix% &#A7F3D0Boss successfully stopped."

    hoe:
      player-only: "%prefix% &#EF4444This command can only be used by a player, or you must specify a target."
      not-holding: "%prefix% &#EF4444{player} must hold a &#FDE047Tycoon Hoe &#EF4444in their main hand."
      uid-missing: "%prefix% &#EF4444The hoe in &#FDE047{player}&#EF4444's hand is missing its internal ID. Please re-create it."
      db-error: "%prefix% &#EF4444Failed to update the hoe. &#9CA3AFCheck the console for more details."
      level:
        self: "%prefix% &#A7F3D0Your hoe level has been set to &#FDE047{level}&#A7F3D0."
        other: "%prefix% &#A7F3D0Set &#93C5FD{player}&#A7F3D0's hoe level to &#FDE047{level}&#A7F3D0."
        target: "%prefix% &#A7F3D0Your hoe level has been set to &#FDE047{level}&#A7F3D0 by an administrator."
      prestige:
        self: "%prefix% &#A7F3D0Your hoe prestige has been set to &#FDE047{prestige}&#A7F3D0."
        other: "%prefix% &#A7F3D0Set &#93C5FD{player}&#A7F3D0's hoe prestige to &#FDE047{prestige}&#A7F3D0."
        target: "%prefix% &#A7F3D0Your hoe prestige has been set to &#FDE047{prestige}&#A7F3D0 by an administrator."

    crystal:
      unknown: "%prefix% &#EF4444Unknown crystal: &#FDE047{id}"
      invalid-level: "%prefix% &#EF4444Invalid crystal level. &#9CA3AF(Max: &#FDE047{max}&#9CA3AF)"
      give:
        sender: "%prefix% &#A7F3D0Gave &#38BDF8{amount}x &#FDE047{crystal} &#A7F3D0(level &#FDE047{level}&#A7F3D0) to &#93C5FD{player}"
        target: "%prefix% &#A7F3D0You received &#38BDF8{amount}x &#FDE047{crystal} &#A7F3D0(level &#FDE047{level}&#A7F3D0)"
      list:
        empty: "%prefix% &#EF4444No crystals loaded."
        entry: "&#A7F3D0- &#FDE047{id} &#9CA3AF(max level: &#E5E7EB{max}&#9CA3AF)"
      slots:
        not-holding: "%prefix% &#EF4444{player} must hold a &#FDE047Tycoon Hoe &#EF4444in their main hand."
        give: "%prefix% &#A7F3D0Added &#FDE047{amount} &#A7F3D0crystal slots to &#93C5FD{player}"
        set: "%prefix% &#A7F3D0Crystal slot count set to &#FDE047{count} &#A7F3D0for &#93C5FD{player}"

  armor:
    unlock:
      success: "%prefix% &#A7F3D0Unlocked &#FDE047{armor}"
      not-enough: "%prefix% &#EF4444You need &#FDE047{cost} &#EF4444essence."
      prestige-required: "%prefix% &#EF4444Required Prestige: &#FDE047{prestige}"

    activate: "%prefix% &#A7F3D0Activated &#FDE047{armor}"
    deactivate: "%prefix% &#F87171Deactivated &#FDE047{armor}"

    upgrade:
      success: "%prefix% &#A7F3D0Upgraded &#FDE047{armor} &#9CA3AFto level &#FDE047{level}"
      max: "%prefix% &#F59E0BArmor already at max level."
      not-enough: "%prefix% &#EF4444You need &#FDE047{cost} &#EF4444essence."

version: '1'
```


# prestige.yml

***

```yaml
prestige-requirements:
  auto-on-eligible: true
  reset-on-prestige: true
  max-prestige: 150

  gui:
    currency:
      format-ok: "&#A7F3D0{amount} {currency}"
      format-missing: "&#F87171{amount} {currency}"
      joiner: "\n"

  boost-per-level:
    essence: 0.25
    crop: 0.10
    xp: 0.20
    enchant-activation: 0.08

  levels:
    '1':
      hoe-level: 5
      requirements:
        - type: currency
          currency: vault
          amount: 5000
      rewards:
        - "[command] eco give {player} 500"
        - "[message] &aPrestige Level Up!"
    '2':
      hoe-level: 15
      rewards:
        - "[command] eco give {player} 1500"
        - "[message] &aPrestige Level Up!"

messages:
  actionbar: "&#A7F3D0+{xp} XP &#9CA3AF| &#6EE7F9+{essence} Essence &#9CA3AF| &#FDE68APrestige {prestige}"
  levelup-title:
    title: "&aPrestige Up!"
    subtitle: "&7You are now Prestige &e{prestige}"
    fade-in: 10
    stay: 40
    fade-out: 10
  levelup-sound: "ui.toast.challenge_complete"

version: "1"
```


# skins.yml

***

```yaml
skins:
  wooden:
    item: WOODEN_HOE
    custom-model-data: 10010
    display-name: "&#D4A373&lW&#C99766&lo&#BE8B59&lo&#B37F4C&ld&#A8733F&le&#9D6732&ln &#925B25&lH&#874F18&lo&#7C430B&le"
    lore:
      - "&#9CA3AFLightweight and reliable."
      - "&#9CA3AFCrafted for early farming."

  stone:
    item: STONE_HOE
    custom-model-data: 10510
    display-name: "&#D1D5DB&lS&#B7BEC7&lt&#9DA6B3&lo&#838F9F&ln&#69778B&le &#4F5F77&lH&#455567&lo&#3B4B57&le"
    lore:
      - "&#9CA3AFDurable for steady work."
      - "&#9CA3AFA solid upgrade from wood."

  iron:
    item: IRON_HOE
    custom-model-data: 11010
    display-name: "&#F3F4F6&lI&#E4E6EB&lr&#D6D9E0&lo&#C7CBD6&ln &#B9BFCB&lH&#AAB2C1&lo&#9CA6B7&le"
    lore:
      - "&#9CA3AFRefined balance and speed."
      - "&#9CA3AFTrusted tool for growth."

  golden:
    item: GOLDEN_HOE
    custom-model-data: 11510
    display-name: "&#FDE68A&lG&#FAD97C&lo&#F7CC6E&ll&#F4BF60&ld&#F1B252&le&#EDA544&ln &#EA9736&lH&#E78A28&lo&#E47D1A&le"
    lore:
      - "&#9CA3AFGleaming style, swift swings."
      - "&#9CA3AFHandle with care—it's soft."

  netherite:
    item: NETHERITE_HOE
    custom-model-data: 12510
    display-name: "&#C4B5FD&lN&#B29AFB&le&#A07FF9&lt&#8E64F7&lh&#7C49F5&le&#6A2EF3&lr&#5813F1&li&#4C0CE6&lt&#4107DA&le &#3602CE&lH&#2B00C2&lo&#2100B6&le"
    lore:
      - "&#9CA3AFTop-tier strength and status."
      - "&#9CA3AFForged for endgame fields."


version: '1'
```


# armors.yml

***

```yaml
armors:
  farmer:
    display:
      selector:
        material: LEATHER_CHESTPLATE
        name: '&aFarmer Armor'
        custom-model-data: 101
        lore:
          - '&7Boosts farming efficiency'
          - '&7Upgrade to increase bonuses'

    pieces:
      helmet:
        material: LEATHER_HELMET
        color: '#7FBF6A'
        name: '&aFarmer Helmet'
        custom-model-data: 201
        lore:
          - '&7Part of the Farmer set'

      chestplate:
        material: LEATHER_CHESTPLATE
        color: '#7FBF6A'
        name: '&aFarmer Chestplate'

      leggings:
        material: LEATHER_LEGGINGS
        color: '#7FBF6A'
        name: '&aFarmer Leggings'

      boots:
        material: LEATHER_BOOTS
        color: '#7FBF6A'
        name: '&aFarmer Boots'

    unlock:
      cost:
        essence: 25000
      require-prestige: 2

    max-level: 20

    levels:
      upgrade-cost:
        base: 500
        per-level: 150
      boosters:
        essence:
          base: 0.5
          per-level: 1
          max: 5.0

    order: 1

  miner:
    display:
      selector:
        material: IRON_CHESTPLATE
        name: '&bMiner Armor'
        custom-model-data: 102
        lore:
          - '&7Boosts mining efficiency'
          - '&7Upgrade to increase bonuses'

    pieces:
      helmet:
        material: IRON_HELMET
        name: '&bMiner Helmet'

      chestplate:
        material: IRON_CHESTPLATE
        name: '&bMiner Chestplate'

      leggings:
        material: IRON_LEGGINGS
        name: '&bMiner Leggings'

      boots:
        material: IRON_BOOTS
        name: '&bMiner Boots'

    unlock:
      cost:
        essence: 35000
      require-prestige: 3

    max-level: 25

    levels:
      upgrade-cost:
        base: 500
        per-level: 150
      boosters:
        hoe-xp:
          base: 0.5
          per-level: 1
          max: 5.0

    upgrade-cost:
      base: 900
      per-level: 250

    order: 2

  hunter:
    display:
      selector:
        material: DIAMOND_CHESTPLATE
        name: '&cHunter Armor'
        custom-model-data: 103
        lore:
          - '&7Boosts mob hunting rewards'
          - '&7Upgrade to increase bonuses'

    pieces:
      helmet:
        material: DIAMOND_HELMET
        name: '&cHunter Helmet'

      chestplate:
        material: DIAMOND_CHESTPLATE
        name: '&cHunter Chestplate'

      leggings:
        material: DIAMOND_LEGGINGS
        name: '&cHunter Leggings'

      boots:
        material: DIAMOND_BOOTS
        name: '&cHunter Boots'

    unlock:
      cost:
        essence: 50000
      require-prestige: 4

    max-level: 30

    levels:
      upgrade-cost:
        base: 500
        per-level: 150
      boosters:
        crops:
          base: 0.5
          per-level: 1
          max: 5.0

    upgrade-cost:
      base: 1400
      per-level: 350

    order: 3

  alchemist:
    display:
      selector:
        material: GOLDEN_CHESTPLATE
        name: '&eAlchemist Armor'
        custom-model-data: 104
        lore:
          - '&7Boosts essence gain'
          - '&7Upgrade to increase bonuses'

    pieces:
      helmet:
        material: GOLDEN_HELMET
        name: '&eAlchemist Helmet'

      chestplate:
        material: GOLDEN_CHESTPLATE
        name: '&eAlchemist Chestplate'

      leggings:
        material: GOLDEN_LEGGINGS
        name: '&eAlchemist Leggings'

      boots:
        material: GOLDEN_BOOTS
        name: '&eAlchemist Boots'

    unlock:
      cost:
        essence: 60000
      require-prestige: 5

    max-level: 30

    levels:
      upgrade-cost:
        base: 500
        per-level: 150
      boosters:
        crops:
          base: 0.5
          per-level: 1
          max: 5.0

    upgrade-cost:
      base: 2000
      per-level: 500

    order: 4

  tycoon:
    display:
      selector:
        material: NETHERITE_CHESTPLATE
        name: '&5Tycoon Armor'
        custom-model-data: 105
        lore:
          - '&7Boosts all activities'
          - '&7The ultimate prestige set'

    pieces:
      helmet:
        material: NETHERITE_HELMET
        name: '&5Tycoon Helmet'

      chestplate:
        material: NETHERITE_CHESTPLATE
        name: '&5Tycoon Chestplate'

      leggings:
        material: NETHERITE_LEGGINGS
        name: '&5Tycoon Leggings'

      boots:
        material: NETHERITE_BOOTS
        name: '&5Tycoon Boots'

    unlock:
      cost:
        essence: 150000
      require-prestige: 7

    max-level: 40

    levels:
      upgrade-cost:
        base: 500
        per-level: 150
      boosters:
        activation:
          base: 0.5
          per-level: 1
          max: 5.0

    upgrade-cost:
      base: 5000
      per-level: 1200

    order: 5

version: '1'
```


# Features

***

{% content-ref url="/pages/a3pxVY7VYNpW7ySak6MG" %}
[config.yml](/premium-products/mc-tycoonhoe/config-files/config.yml)
{% endcontent-ref %}


# Farm System

The Farm System is the core harvesting engine of Tycoon.

It controls crop behavior, XP gain, essence rewards, custom drops, evolution items and growth rendering.

The system is area-based, performance-safe and supports both client-side and server-side crop rendering.

***

## Farm Area

```yaml
farm:
  trigger: WHEAT
  area:
    world: ""
    min: [0, 0, 0]
    max: [0, 0, 0]
```

#### trigger

Defines the main crop type used inside the farm area.

#### area

Defines the rectangular region where special farm logic applies.

If empty → system behaves globally.

***

## Harvest Rules

```yaml
harvest:
  require-grown: true
```

If `true`, ageable crops must be fully grown before harvesting.

***

## Render Mode

```yaml
render-mode: SERVER
```

Available modes:

* `SERVER`
* `CLIENT`

This controls how crop breaking and regrowth are handled.

***

## SERVER Mode (Authoritative)

Default and safest option.

#### Behavior

* Blocks are physically modified on the server
* Real block data changes
* Uses region scheduler for growth
* Fully synchronized across all players
* No fake block states

#### Growth Logic

* Ageable crops replant at age 0
* Grow per stage with configurable tick delay
* Double-height plants restore properly
* Sugar cane restores correctly with height validation

#### Best For

* Competitive servers
* Boss damage systems
* Shared farming environments
* High player count farms

***

## CLIENT Mode (Visual-Only Masking)

Optimized personal rendering.

#### Behavior

* Real block is not removed
* Player receives fake block change
* Regrowth happens client-side only
* Other players see original block state
* Fully personal harvesting illusion

#### How It Works

* Uses `sendBlockChange`
* Registers fake harvest entries
* Schedules client-only restoration
* Does not modify world state

#### Options

```yaml
growth:
  enabled: true
  ticks-per-stage: "8-12"
  double-height-restore: "20"
  single-restore: "20"

client:
  keep-final-stage: true
```

* `ticks-per-stage` → random growth interval
* `double-height-restore` → restore delay
* `single-restore` → restore delay
* `keep-final-stage` → keep visually mature

#### Best For

* Personal farms
* Skyblock-style islands
* High-performance setups
* Visual-only crop systems

***

## Growth System

```yaml
growth:
  enabled: true
  ticks-per-stage: "8-12"
```

Supports:

* Fixed value: `10`
* Range: `"8-12"`

Each growth stage delay is randomly selected in range.

***

## Drop System

```yaml
drop-settings:
  straight-to-inventory: true
  drop-items-floor-if-full-inventory: false
```

#### straight-to-inventory

Directly inserts drops into player inventory.

#### drop-items-floor-if-full-inventory

If inventory full:

* true → drop on ground
* false → stop giving drops

Supports stacking and storage hooks.

***

## Harvest Rule Structure

```yaml
WHEAT:
  xp: "50-70"
  min-level: 2
  essence: 3
```

#### xp

* Single value
* Range `"min-max"`

#### min-level

Minimum Tycoon Hoe level required.

#### essence

Supports:

* Single value
* Range `"min-max"`

***

## Custom Drop Items

```yaml
drop:
  amount: 1-3
  material: "WHEAT"
  name: "Fresh Wheat"
  lore:
    - "Harvested with love"
```

Supports:

* Custom name
* Lore
* Enchantments
* Flags
* Unbreakable
* Custom model data
* Full ItemFactory integration

***

## Evolution Items

```yaml
evolution-item:
  material: "WHEAT"
  needed-amount: 5
  name: "Baked Wheat"
```

If player collects required amount → converts to evolution item.

Evolution can be placed inside:

* `drop.evolution-item`
* Or directly under rule

***

## XP & Essence Calculation Flow

Final gain includes:

* Base XP
* Enchant bonuses
* Prestige bonuses
* Armor boosters
* Pet boosts
* Power-up boosts

Formula pipeline:

```yaml
base → enchant → prestige → armor → pet → powerup
```

All boosts are additive before rounding.

***

## Rounding Modes

Crop yield boosters support:

* STOCHASTIC
* ROUND
* FLOOR
* CEIL

Configured under enchant settings.

***

## Boss Integration

Each crop break automatically notifies:

```java
BossManager.handleCropBreak()
```

Boss damage is directly tied to farm activity.

***

## Safety & Performance

* ConcurrentHashMap stacking buffers
* Essence batching (500ms window)
* XP batching (5s window)
* No sync database writes
* RegionScheduler for growth
* No heavy tick loops
* Fully event-driven

***

## Double Height Handling

Supported:

* Sugar Cane
* Sunflower
* Lilac
* Rose Bush
* Peony
* All Bisected blocks

Prevents bottom-half breaking exploits.


# Tycoon Boss System

The Tycoon Boss System is a timed global farming event where players deal damage by breaking crops.

Damage is tracked per player, ranked, rewarded and broadcasted in real time.

This is not a mob-based combat boss.\
It is a server-wide competitive farming event tied directly to crop activity.

***

## Core Concept

Each boss consists of:

* A unique ID
* A display name
* A maximum HP
* A timeout duration
* Crop damage rules
* Optional visual representation
* Optional BossBar
* Start & end broadcasts
* Ranked reward distribution
* Participant rewards
* Scheduler triggers
* Personal statistics messaging

Only one boss can be active at a time.

***

## Boss Configuration Structure

```yaml
bosses:
  <BOSS_ID>:
```

Boss IDs are stored uppercase internally.

***

## Basic Configuration

```yaml
CARROT_KING:
  name: Carrot King
  max-hp: 2500
  timeout: "1h"
```

#### Fields

| Field     | Description    |
| --------- | -------------- |
| `name`    | Display name   |
| `max-hp`  | Total HP       |
| `timeout` | Event duration |

***

## Timeout Format

Supported formats:

* `30s`
* `15m`
* `2h`
* `1d`
* `5000ms`
* raw milliseconds

If timeout is reached and boss is not killed → event ends without kill rewards.

***

## Damage System

Bosses take damage from crop breaking.

```yaml
damage:
  default: 2
  overrides:
    CARROTS: 3
    WHEAT: 1
```

#### How It Works

* `default` → applied to all crops
* `overrides` → material-specific damage
* Final damage is scaled by enchant bonuses
* Damage cannot be negative
* Custom `BossDamageEvent` is fired

***

## Boss Visual System

Global visual configuration:

```yaml
visual:
  spawn-location:
    world: "world"
    x: 0.5
    y: 100
    z: 0.5
  height-offset: 0
```

Per-boss visual:

```yaml
visual:
  type: HEAD
```

#### Supported Types

### HEAD

```yaml
visual:
  type: HEAD
  head:
    owner: "CarrotKing"
    # texture: "base64"
  display:
    scale: 2.5
    yaw: 0
    pitch: 0
```

Options:

* `owner` → Player skull owner
* `texture` → Base64 custom texture
* `scale` → Display scaling
* `yaw`, `pitch` → Rotation

***

### MODEL (ModelEngine)

```yaml
visual:
  type: MODEL
  model-id: "carrot_king"
```

Spawns invisible pig carrier entity and attaches ModelEngine model.

***

## BossBar

```yaml
bossbar:
  enabled: true
  title: "{boss_name} - {hp}/{max} ({percent}%)"
  color: RED
  style: SEGMENTED_20
  update-interval: 5
```

#### Supported Colors

* RED
* BLUE
* GREEN
* YELLOW
* PURPLE
* PINK
* WHITE

#### Supported Styles

* SOLID
* SEGMENTED\_6
* SEGMENTED\_10
* SEGMENTED\_12
* SEGMENTED\_20

***

## Start Broadcast

```yaml
start-broadcast:
  - "Boss started!"
```

Placeholders:

* `{boss_name}`
* `{hp}`
* `{max}`
* `{time}`

***

## End Broadcast

```yaml
end-broadcast:
  limit: 3
  header:
  ranks:
  footer:
  personal:
```

#### limit

Maximum ranks displayed publicly.

***

#### Rank Sections

Supports:

* Exact rank: `"1"`
* Range: `"3-5"`
* `default`

Placeholders:

* `{player}`
* `{rank}`
* `{damage}`
* `{dmg_ratio}`
* `{boss_name}`

***

#### Personal Section

Sent to each player individually.

Placeholders:

* `{damage}`
* `{dmg_ratio}`
* `{rank}`

***

## Rewards System

```yaml
rewards:
  top:
    limit: 5
    per-rank:
      "1":
        - "eco give {player} 10000"
      "2":
        - "eco give {player} 7500"
      "3-5":
        - "eco give {player} 5000"
      default:
        - "eco give {player} 2000"
  participants:
    min-damage: 100
    commands:
      - "eco give {player} 150"
```

#### Top Rewards

* `limit` → number of ranked rewards
* `per-rank` supports:
  * exact rank
  * rank ranges
  * default fallback

***

#### Participant Rewards

* `min-damage` → required to receive reward
* Commands executed from console
* `{player}`, `{damage}`, `{rank}`, `{dmg_ratio}` supported

***

## Scheduler System

Bosses can auto-start via triggers.

```yaml
triggers:
  - boss-id: CARROT_KING
    when: every:2h
    conditions:
      - "[player>=50]"
```

***

### Trigger Timing

#### Fixed Interval

```yaml
when: every:15m
```

#### Random Interval

```yaml
when: random:10m..30m
```

#### Direct Duration

```yaml
when: 1h
```

***

### Conditions

Currently supported:

```python
[player>=50]
[player<=30]
[player=100]
[player>10]
[player<200]
```

Checks online player count.

If conditions fail → trigger postponed.


# Tycoon Boost Armors

Tycoon Boost Armors are progression-based armor sets that grant scalable bonuses tied to player level, prestige and essence investment.

\
Each armor is fully configurable, supports custom visuals (including Nexo items), persistent levels, unlock requirements and dynamic boosters that scale per level.

This system is not cosmetic-only. It is a structured progression layer designed to integrate directly into farming, mining and economy mechanics.

***

### Core Concept

Every armor consists of:

* A **selector item** (used in GUI)
* Four **equipment pieces** (helmet, chestplate, leggings, boots)
* An **unlock condition**
* A **max level**
* A **level scaling system**
* One or multiple **boosters**
* A **display order**
* Persistent player state (unlocked, level, active armor)

Only one armor can be active at a time.

***

## Armor Configuration Structure

```
armors:
  <armor-id>:
```

Each armor ID is unique and used internally for storage and activation.

***

### 1. Display (Selector Item)

```yaml
display:
  selector:
    material: LEATHER_CHESTPLATE
    name: '&aFarmer Armor'
    custom-model-data: 101
    lore:
      - '&7Boosts farming efficiency'
```

#### Supported Options

| Field               | Required | Description                    |
| ------------------- | -------- | ------------------------------ |
| `material`          | Yes      | Bukkit material OR `nexo:<id>` |
| `name`              | No       | Display name                   |
| `lore`              | No       | List of lore lines             |
| `custom-model-data` | No       | Integer                        |
| `color`             | No       | HEX color (leather only)       |

#### Nexo Support

You can use:

```yaml
material: "nexo:my_custom_item"
```

If the value starts with `nexo:` it will be treated as a Nexo item instead of Bukkit material.

***

### 2. Pieces

```yaml
pieces:
  helmet:
    material: LEATHER_HELMET
    color: '#7FBF6A'
    name: '&aFarmer Helmet'
```

Supported piece keys:

* `helmet`
* `chestplate`
* `leggings`
* `boots`

All fields supported by selector are also supported here:

* material / nexo
* name
* lore
* custom-model-data
* color

If a piece is missing, it simply won’t be equipped.

***

### 3. Unlock System

```yaml
unlock:
  cost:
    essence: 25000
  require-prestige: 2
```

#### Options

| Field              | Description                |
| ------------------ | -------------------------- |
| `cost.essence`     | Essence required to unlock |
| `require-prestige` | Minimum prestige required  |

Unlocking:

* Marks armor as unlocked
* Initializes its level at 0
* Persists in database

***

### 4. Level System

```yaml
max-level: 20
```

Defines the maximum level for that armor.

Level progression is stored per player per armor.

***

### 5. Upgrade Cost Scaling

```yaml
levels:
  upgrade-cost:
    base: 500
    per-level: 150
```

Upgrade formula:

```java
cost = base + (current_level * per-level)
```

This allows fully linear scaling.

You can design:

* Cheap early scaling
* Exponential feeling via large per-level values
* High-end progression caps

***

### 6. Boosters

```yaml
levels:
  boosters:
    essence:
      base: 0.5
      per-level: 1
      max: 5.0
```

Each booster has:

| Field       | Description               |
| ----------- | ------------------------- |
| `base`      | Starting value at level 1 |
| `per-level` | Increase per level        |
| `max`       | Hard cap                  |

#### Available Booster Keys (Standard Usage)

The following booster keys are commonly used across Tycoon systems:

* **essence** → Increases essence gain
* **crops** → Increases crop rewards / yield
* **hoe-xp** → Increases Tycoon Hoe XP gain
* **activation** → Increases activation chance / proc-based effects

Calculation:

```yaml
value = base + ((level - 1) * per-level)
value = min(value, max)
```

Boosters are referenced by string key:

```java
ArmorBoosterService.getBooster(playerUUID, "essence")
```

Keys are lowercase internally.

You can define multiple boosters:

```yaml
boosters:
  essence:
    base: 0.5
    per-level: 1
    max: 5
  crops:
    base: 1
    per-level: 0.5
    max: 10
```

There is no hard limit on booster count.

***

### 7. Order

```yaml
order: 1
```

Used for GUI sorting. Lower number appears first.

***

## GUI Configuration

```yaml
armor:
```

Fully configurable inventory.

***

### Inventory Settings

```yaml
title: "&8        ᴛʏᴄᴏᴏɴ ᴀʀᴍᴏʀ ꜱᴇᴛꜱ"
size: 54
```

***

### Selector Slots

```yaml
selector-slots: [10,11,12,13,14,15,16]
```

Armor selector icons are placed here in order.

***

### Piece Slots

```yaml
piece-slots:
  helmet: 20
  chestplate: 21
  leggings: 22
  boots: 23
```

***

### Piece Template

This controls how upgrade items look dynamically.

```yaml
piece-template:
  name: "{display_name} Lv. {level}"
  lore:
    - "{description}"
    - "Max Level: {max_level}"
    - "Booster: {booster}"
```

#### Supported Placeholders

| Placeholder          | Meaning                  |
| -------------------- | ------------------------ |
| `{display_name}`     | Armor display name       |
| `{level}`            | Current level            |
| `{max_level}`        | Maximum level            |
| `{description}`      | Booster description      |
| `{upgrade_1_cost}`   | Cost for +1              |
| `{upgrade_50_cost}`  | Cost for +50             |
| `{upgrade_max_cost}` | Cost for max             |
| `{boost-type}`       | Booster key              |
| `{booster}`          | Current calculated value |

Upgrade interaction types:

* Left Click → +1
* Right Click → +50
* Q → Max upgrade

***

### GUI Buttons

```yaml
items:
  unlock:
  activate:
  deactivate:
  back:
```

Each supports:

* slot list
* material
* name
* lore

You can fully redesign visual style.

***

## Player State Model

Each player stores:

* activeArmorId
* unlocked armors
* level per armor
* dirty flag (for database flush)

State is cached in memory and periodically flushed to database.

***

## Persistence & Performance

* Async loading
* Async saving
* Dirty-check flush task
* No sync database operations
* Thread-safe cache (ConcurrentHashMap)

Armor activation:

* Instantly equips pieces
* Updates inventory
* Marks state dirty

***

## Creating a New Armor (Template)

Copy and modify:

```yaml
armors:
  harvester:
    display:
      selector:
        material: LEATHER_CHESTPLATE
        name: '&2Harvester Armor'
        custom-model-data: 110

    pieces:
      helmet:
        material: LEATHER_HELMET
        color: '#4CAF50'
        name: '&2Harvester Helmet'

      chestplate:
        material: LEATHER_CHESTPLATE
        color: '#4CAF50'

      leggings:
        material: LEATHER_LEGGINGS
        color: '#4CAF50'

      boots:
        material: LEATHER_BOOTS
        color: '#4CAF50'

    unlock:
      cost:
        essence: 75000
      require-prestige: 6

    max-level: 35

    levels:
      upgrade-cost:
        base: 800
        per-level: 200
      boosters:
        crops:
          base: 1.0
          per-level: 0.8
          max: 12

    order: 6
```

***

## Design Recommendations

• Early game: low max-level, low base, soft scaling\
• Mid game: moderate scaling, dual boosters\
• Late game: high cap, prestige gated\
• End game: multi-booster stacking

You can:

* Create specialization armors
* Create hybrid armors
* Create prestige-exclusive sets
* Design armor tiers aligned with server economy


# Anti Macro Farming

## Anti-Macro System

The plugin includes a built-in anti-macro system designed to prevent automated farming.

During crop harvesting, player interactions are observed over time. Instead of reacting to single actions, the system evaluates behavior patterns to determine whether the activity appears natural.

If a pattern looks suspicious, the plugin may open a short verification menu.\
The player must interact with the menu to confirm that they are actively playing.

Failing or ignoring the verification can result in a disconnect.

The system is designed to stay invisible during normal gameplay and only activate when behavior strongly resembles automated interaction.

For security reasons, the internal detection logic is not publicly documented.

{% hint style="danger" %}
Revealing how the system works internally would make it easier for macros or automation tools to bypass the protection.
{% endhint %}


# AFK Farming System

## AFK Farming System

The AFK system allows players to automatically harvest crops while remaining inside the farm area.\
Instead of breaking blocks physically, the system simulates harvesting and rewards the player with:

* Hoe XP
* Essence
* Crop drops
* Level rewards

This system is designed to be **lightweight and server-safe**, avoiding block updates, enchant triggers, boss damage, or visual harvest logic.

***

## How AFK Farming Works

When AFK farming starts, a session is created for the player.

During the session the system will periodically:

1. Determine the player's active crop.
2. Simulate crop harvesting.
3. Grant:
   * Hoe XP
   * Essence
   * Crop items
4. Send income feedback via the actionbar.
5. Display a title showing remaining AFK time.

No physical blocks are broken during this process.

***

## AFK Session

Each player has an AFK session containing:

* Player UUID
* Session start time
* Session end time
* Crops generated per tick
* Last database save timestamp

Sessions automatically stop when:

* The player moves
* The player leaves the server
* The player leaves the farm area
* The player stops holding a Tycoon Hoe
* The AFK duration expires

***

## AFK Groups

AFK behavior is permission-based.\
Each player automatically receives the **best AFK group they have permission for**.

Groups define:

* Maximum AFK duration
* Crops generated per tick

Example configuration:

```yaml
afk:
  groups:
    default:
      permission: mctycoonhoe.afk.default
      max-time: 1h
      crops-per-tick: 2

    vip:
      permission: mctycoonhoe.afk.vip
      max-time: 3h
      crops-per-tick: 4

    legend:
      permission: mctycoonhoe.afk.legend
      max-time: 5h
      crops-per-tick: 6
```

The plugin automatically selects the group with the **highest allowed AFK time**.

***

## Crop Generation

Each AFK tick generates crops based on the player's group:

```
crops generated = crops-per-tick
```

For every generated crop the system applies the normal harvest rules:

* XP from the crop
* Essence rewards
* Drop table from the crop
* Hoe level progression

Drops are handled through the normal item storage hook if available.

***

## Item Handling

If a supported storage plugin is installed, crop drops will attempt to go directly into storage first.

If storage cannot accept the items, they will be placed in the player's inventory.

***

## Actionbar Income

AFK farming provides income feedback through the actionbar.

Income values are automatically stacked for a short window to prevent spam.

Example:

```
+125 XP | +80 Essence
```

The format can be configured through:

```
leveling.notify.farm-actionbar
```

***

## AFK Title Display

While AFK farming is active, a title can be shown to the player displaying:

* Remaining AFK time
* Crops generated per tick

Example configuration:

```
afk:
  title:
    enabled: true
    header: "&aAFK Farming"
    subtitle: "&7Time left: &e{time} &7• &a{crops} crops/tick"
```

Available placeholders:

| Placeholder | Description              |
| ----------- | ------------------------ |
| `{time}`    | Remaining AFK time       |
| `{crops}`   | Crops generated per tick |

***

## AFK Cancellation

AFK farming stops automatically if the player:

* Moves
* Leaves the farm area
* Leaves the server
* Stops holding a Tycoon Hoe

Messages are configurable:

| Message Key                    | Trigger                            |
| ------------------------------ | ---------------------------------- |
| `messages.afk.cancel-move`     | Player moved                       |
| `messages.afk.cancel-leave`    | Session expired or player left     |
| `messages.afk.not-in-farm`     | Player left farm area              |
| `messages.afk.not-holding-hoe` | Player is not holding a Tycoon Hoe |

***

## Performance

The AFK system is designed to avoid heavy operations.

It does **not**:

* Break real blocks
* Trigger enchant effects
* Trigger boss damage
* Update crop statistics
* Spawn visual harvest effects

This makes the system safe for long AFK sessions and large farms.


# Supported Plugins

***

Supported Plugins list:

```yaml
- mc-ItemStorage
- ProtocolLib
- ModelEngine
- PlaceholderAPI
- mc-Friends
- AxBoosters
- BattlePass
- mc-TycoonPet
- mc-PowerUp
```


# PlaceholderAPI

The plugin support PlaceholderAPI and have different placeholders.

***

<table><thead><tr><th width="374">Placeholder</th><th>Output</th></tr></thead><tbody><tr><td>tycoonhoe_prestige</td><td>highest prestige number</td></tr><tr><td>tycoonhoe_essence</td><td>raw essence value</td></tr><tr><td>tycoonhoe_essence_formatted</td><td>formatted essence value</td></tr><tr><td></td><td></td></tr><tr><td>tycoonhoe_farm_crop</td><td>player active crop name</td></tr><tr><td></td><td></td></tr><tr><td>tycoonhoe_notify_actionbar</td><td>active/inactive (1/0)</td></tr><tr><td>tycoonhoe_notify_message</td><td>active/inactive (1/0)</td></tr><tr><td>tycoonhoe_notify_title</td><td>active/inactive (1/0)</td></tr><tr><td>tycoonhoe_notify_sound</td><td>active/inactive (1/0)</td></tr><tr><td></td><td></td></tr><tr><td>tycoonhoe_boss_active</td><td>true/false</td></tr><tr><td>tycoonhoe_boss_next</td><td>formatted next boss time</td></tr><tr><td>tycoonhoe_boss_active_display_name</td><td>active boss display name</td></tr><tr><td>tycoonhoe_boss_active_current_hp</td><td>active boss current hp value</td></tr><tr><td>tycoonhoe_boss_active_max_hp</td><td>active boss max hp value</td></tr><tr><td>tycoonhoe_boss_active_timeout</td><td>active boss formatted timeout</td></tr><tr><td>tycoonhoe_boss_active_id</td><td>active boss id value</td></tr><tr><td>tycoonhoe_boss_active_min_damage</td><td>active boss required min damage value</td></tr><tr><td>tycoonhoe_boss_active_damage_&#x3C;pos>_name</td><td>active boss top damager name</td></tr><tr><td>tycoonhoe_boss_active_damage_&#x3C;pos>_value</td><td>active boss top damager damage value</td></tr><tr><td>tycoonhoe_boss_active_player_rank</td><td>active boss personal damage rank </td></tr><tr><td>tycoonhoe_boss_active_player_damage</td><td>active boss personal damage value</td></tr><tr><td></td><td></td></tr><tr><td>tycoonhoe_top_prestige_&#x3C;position>_name</td><td>top prestige player name by position </td></tr><tr><td>tycoonhoe_top_prestige_&#x3C;position>_value</td><td>top prestige player value by position </td></tr></tbody></table>


# BattlePass

The plugin has 9 type of BattlePass Quest

***

{% hint style="warning" %}
All the Quest IDs has to contain McTycoonHoe, for example: `McTycoonHoe_condense`
{% endhint %}

| Quest ID                  | Variable                               |
| ------------------------- | -------------------------------------- |
| boss-damage               | Boss Id, for example: CARROT\_KING     |
| condense                  | Crop material name, for example: WHEAT |
| crop-harvest              | Crop material name                     |
| enchant\_purchase\_levels | Enchant Id for example: SPEED          |
| enchant\_purchase\_spent  | Enchant Id                             |
| essence-gain              |                                        |
| hoe-levelup               |                                        |
| hoe-xpgain                |                                        |
| prestige-levelup          |                                        |


# 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+
```


# mc-Quests

Modern RPG-Styled Quest manager plugin with modern solutions.

<figure><img src="/files/wSvcAzyzkKxlTcIHdbNw" alt=""><figcaption></figcaption></figure>

***

#### Plugin Features

* High Optimized plugin, the plugin does not cause lags
* 1.18+ Version Support
* Hex Color code Support
* Folia Support
* GUI Based System
* Easy to customizable
* Daily Quest Board
* In-built Level System
* Level based player Quests
* 40+ Quest Trigger

{% content-ref url="/pages/TjfeFIlzSReTruJvLgMs" %}
[Config Files](/premium-products/mc-tycoonhoe/config-files)
{% endcontent-ref %}


# Config Files

***

{% content-ref url="/pages/a3pxVY7VYNpW7ySak6MG" %}
[config.yml](/premium-products/mc-tycoonhoe/config-files/config.yml)
{% endcontent-ref %}


# config.yml

***

```yaml
database:
  # H2, MySQL
  type: "h2"

  mysql:
    host: "localhost"
    port: 3306
    database: "database"
    username: "username"
    password: "password"

  pool:
    maximumPoolSize: 10
    minimumIdle: 5
    connectionTimeout: 30000
    maxLifetime: 1800000
    idleTimeout: 600000
    setLeakDetectionThreshold: 60000
    useSSL: false

leveling:
  base-xp: 100
  scale: 1.5

  level-up:
    commands:
      - "eco give %player% 50"

    rewards:
      default:
        commands:
          - "eco give %player% 100"

      levels:
        5:
          commands:
            - "give %player% diamond 1"

        10:
          commands:
            - "crate give %player% epic 1"

        20:
          commands:
            - "lp user %player% permission set quests.vip"

quests:
  limits:
    max-accepted:
      base: 3
      per-level: 10
    max-active:
      base: 1
      per-level: 20

  progress:
    enabled: true
    milestones: [25, 50, 75, 100]

    message: "&aProgress: &e{percent}% &7({current}/{required})"
    actionbar: "&e{percent}% completed"

    sound: "minecraft:block.note_block.hat"

  complete:
    message: "&#7CF6FF&lQUEST COMPLETE &#8A8F98» &#FFFFFF{quest_name}"
    sound: "minecraft:ui.toast.challenge_complete"

  objective-complete:
    message: "&#8DFFB3✔ &#C7D0D9Objective complete: &#FFFFFF{objective_name}"
    sound: "minecraft:block.note_block.pling"

  daily-board:
    base: 5
    per-level: 5
    level-range: 15
    reset-time: "04:00"
    timezone: "Europe/Budapest"

  expire-warning:
    enabled: true
    percentage:
      - 50
      - 15
      - 5

premium:
  bonus:
    max-accepted: 3
    max-active: 1
    daily-board: 2

  multipliers:
    xp: 1.25
    reward: 1.5

placeholders:
  level:
    placeholder-condition:
      enabled: true
      levels: '%nexo_level_<player_level>%'

    overrides:
      "100": "&6MAX"
      "50": "&eVIP"

update-checker:
  # Periodically checks SpigotMC for a new version (every 30 minutes) and
  # notifies the console + online admins with the 'quests.update-notify' permission.
  enabled: true

version: '1'
```


# guis.yml

***

```yaml
quest-board:
  title: "<dark_gray>Quest Board ({reset})"
  title-premium: "<dark_gray>Premium Quest Board ({reset})"
  size: 54

  sounds:
    open: "block.note_block.pling"
    error: "entity.villager.no"
    action: "entity.experience_orb.pickup"
    reroll: "block.amethyst_block.chime"

  quest-slots: [20, 21, 22, 23, 24, 29, 30, 31, 32, 33]

  quest-template:
    material: TRIAL_KEY
    name: "&#B8FFF2&l{name}"
    flag: [HIDE_ATTRIBUTES]
    lore:
      - ""
      - " &#8A8F98◆ Status: {status}"
      - ""
      - "&#7CF6FF&lOBJECTIVES"
      - "{objectives}"
      - ""
      - "&#FFD86E&lREQUIREMENTS"
      - "{conditions}"
      - ""
      - "&#B8FFF2&lREWARDS"
      - "{rewards}"
      - ""
      - "&#D3DBE3&lTIME LIMIT"
      - "{time}"
      - ""
      - "{action}"

  formats:
    status:
      available: "&#FFD86EAvailable"
      accepted: "&#B8FFF2Accepted"
      completed: "&#7CF6FFCompleted"

    action:
      available: "&#B8FFF2» Left click: Accept quest"
      accepted: "&#8A8F98Already accepted"
      completed: "&#7CF6FFAlready completed"

    empty: "&#7A8592» None"

    objective-line: "&#8A8F98» &#D3DBE3{name}"
    objective-desc: "  &#7A8592• &#C7D0D9{line}"

    condition-line: "&#8A8F98» &#C7D0D9{type}: &#FFFFFF{value}"
    reward-line: "&#8A8F98» &#D3DBE3{name}"

    time-accept: "&#8A8F98» Accept within &#FFFFFF{time}"
    time-complete: "&#8A8F98» Complete within &#FFFFFF{time}"
    time-remaining: "&#8A8F98» Time left &#FFFFFF{time}"

  refresh-cost:
    enabled: false
    placeholder: "%vault_eco_balance%"
    cost: 1000.0
    take-command: "eco take %player% 1000"
    sounds:
      success: "entity.experience_orb.pickup"
      error: "entity.villager.no"
    messages:
      not-enough: "&#FF6B6BYou don't have enough money to reroll your quests."
      success: "&#B8FFF2Your quests have been rerolled for &#FFFFFF{cost}&#B8FFF2."

  items:
    filler:
      material: BLACK_STAINED_GLASS_PANE
      name: " "
      slot: border
      priority: 1

    filler2:
      material: STONE_BUTTON
      name: " "
      slot: [20, 21, 22, 23, 24, 29, 30, 31, 32, 33]

    player:
      material: PLAYER_HEAD
      name: "&#B8FFF2&l{player}"
      flag: [HIDE_ATTRIBUTES]
      slot: 4
      priority: 10
      lore:
        - ""
        - " &#8A8F98◆ Level: &#FFFFFF{level}"
        - " &#8A8F98◆ XP: &#FFFFFF{xp}&#8A8F98/&#FFFFFF{xp-needed} &#7A8592({progress}%)"
        - ""
        - " &#8A8F98◆ Pass: &#FFD86E{pass-type}"
        - " &#8A8F98◆ Active Slots: &#FFFFFF{max-active}"
        - " &#8A8F98◆ Accepted Slots: &#FFFFFF{max-accepted}"
        - " &#8A8F98◆ Daily Quests: &#FFFFFF{daily-board-size}"
        - " &#8A8F98◆ XP Multiplier: &#FFFFFFx{xp-multiplier}"

    player-placeholder:
      material: PLAYER_HEAD
      name: "&#B8FFF2&l{player}"
      flag: [HIDE_ATTRIBUTES]
      slot: 4
      priority: 10
      lore:
        - ""
        - " &#8A8F98◆ Level: &#FFFFFF{level}"
        - " &#8A8F98◆ XP: &#FFFFFF{xp}&#8A8F98/&#FFFFFF{xp-needed} &#7A8592({progress}%)"
        - ""
        - " &#8A8F98◆ Pass: &#FFD86E{pass-type}"

    info:
      material: BAMBOO_HANGING_SIGN
      name: "&#FFD86E&lHow Quests Work"
      slot: 8
      priority: 10
      lore:
        - ""
        - "&#C7D0D9Choose a quest from the board"
        - "&#C7D0D9and accept it to begin."
        - ""
        - "&#8A8F98» Accept quests from this menu"
        - "&#8A8F98» Start them in Active Quests"
        - "&#8A8F98» Earn XP and unlock rewards"

    active:
      material: VAULT
      name: "&#B8FFF2&lActive Quests"
      flag: [HIDE_ATTRIBUTES]
      slot: 47
      priority: 10
      lore:
        - ""
        - "&#C7D0D9View your accepted quests"
        - "&#C7D0D9and start your next challenge."
        - ""
        - "&#B8FFF2» Left click: Open"

    leaderboard:
      material: HEAVY_CORE
      name: "&#C8A2FF&lLeaderboard"
      flag: [HIDE_ATTRIBUTES]
      slot: 49
      priority: 10
      lore:
        - ""
        - "&#C7D0D9View the top quest players"
        - "&#C7D0D9on the server."
        - ""
        - "&#B8FFF2» Left click: Open"

    refresh:
      material: OMINOUS_BOTTLE
      name: "&#7CF6FF&lReroll Quests"
      slot: 51
      priority: 10
      lore:
        - ""
        - "&#C7D0D9Replace your current daily"
        - "&#C7D0D9quests with a fresh set."
        - ""
        - "&#B8FFF2» Left click: Reroll"

quest-active:
  title: "<dark_gray>Active Quests"
  size: 27

  sounds:
    open: "block.note_block.pling"
    error: "entity.villager.no"
    action: "entity.experience_orb.pickup"

  quest-slots: [10, 11, 12, 13, 14, 15, 16]

  quest-template:
    material: WIND_CHARGE
    name: "&#FFD86E&l{name}"
    flag: [HIDE_ATTRIBUTES]
    lore:
      - ""
      - " &#8A8F98◆ Status: {status}"
      - ""
      - "&#7CF6FF&lOBJECTIVES"
      - "{objectives}"
      - ""
      - "&#FFD86E&lREQUIREMENTS"
      - "{conditions}"
      - ""
      - "&#B8FFF2&lREWARDS"
      - "{rewards}"
      - ""
      - "&#D3DBE3&lTIME LIMIT"
      - "{time}"
      - ""
      - "{action}"

  formats:
    status:
      accepted: "&#FFD86EAccepted"
      active: "&#B8FFF2Active"

    action:
      start: "&#B8FFF2» Left click: Start quest"
      accepted: "&#8A8F98Quest in progress"

    empty: "&#7A8592» None"

    objective-line: "&#8A8F98» &#D3DBE3{name}"
    objective-desc: "  &#7A8592• &#C7D0D9{line}"

    condition-line: "&#8A8F98» &#C7D0D9{type}: &#FFFFFF{value}"
    reward-line: "&#8A8F98» &#D3DBE3{name}"

    time-accept: "&#8A8F98» Accept within &#FFFFFF{time}"
    time-complete: "&#8A8F98» Complete within &#FFFFFF{time}"
    time-remaining: "&#8A8F98» Time left &#FFFFFF{time}"

  items:
    filler:
      material: BLACK_STAINED_GLASS_PANE
      name: " "
      slot: border
      priority: 1

    back:
      material: RECOVERY_COMPASS
      name: "&#FF6B6B&lBack"
      slot: 22
      priority: 10
      lore:
        - ""
        - "&#C7D0D9Return to the main"
        - "&#C7D0D9Quest Board menu."
        - ""
        - "&#B8FFF2» Left click: Go back"

leaderboard:
  title: "<dark_gray>Quest Leaderboard"
  size: 54

  sounds:
    open: "block.note_block.pling"
    action: "entity.experience_orb.pickup"

  default-category: LEVEL

  category-format:
    LEVEL: "Level"
    QUESTS_COMPLETED: "Quests Completed"

  entries-slots: [19, 20, 21, 22, 23, 24, 25, 28, 29, 30, 31, 32, 33, 34]

  entry:
    material: PLAYER_HEAD
    name: "&#FFD86E&l#{position} &#FFFFFF{player}"
    flag: [HIDE_ATTRIBUTES]
    lore:
      - ""
      - " &#8A8F98◆ Score: &#FFFFFF{value}"

  items:
    filler:
      material: BLACK_STAINED_GLASS_PANE
      name: " "
      slot: border
      priority: 1

    player:
      material: PLAYER_HEAD
      name: "&#B8FFF2&l{player}"
      flag: [HIDE_ATTRIBUTES]
      slot: 4
      priority: 10
      lore:
        - ""
        - " &#8A8F98◆ Category: &#FFFFFF{category}"
        - ""
        - " &#8A8F98◆ Level: &#FFFFFF{level}"
        - " &#8A8F98◆ XP: &#FFFFFF{xp}"
        - " &#8A8F98◆ Completed: &#FFFFFF{completed}"

    player-placeholder:
      material: PLAYER_HEAD
      name: "&#B8FFF2&l{player}"
      flag: [HIDE_ATTRIBUTES]
      slot: 4
      priority: 10
      lore:
        - ""
        - " &#8A8F98◆ Level: &#FFFFFF{level}"
        - " &#8A8F98◆ Completed: &#FFFFFF{completed}"

    category-level:
      material: MACE
      name: "&#7CF6FF&lTop by Level"
      slot: 11
      priority: 10
      lore:
        - ""
        - "&#C7D0D9Rank players by their"
        - "&#C7D0D9current quest level."
        - ""
        - "&#B8FFF2» Left click: View"

    category-completed:
      material: OMINOUS_TRIAL_KEY
      name: "&#B8FFF2&lTop by Completed"
      flag: [HIDE_ATTRIBUTES]
      slot: 15
      priority: 10
      lore:
        - ""
        - "&#C7D0D9Rank players by their"
        - "&#C7D0D9completed quests."
        - ""
        - "&#B8FFF2» Left click: View"

    back:
      material: RECOVERY_COMPASS
      name: "&#FF6B6B&lBack"
      slot: 49
      priority: 10
      lore:
        - ""
        - "&#C7D0D9Return to the main"
        - "&#C7D0D9Quest Board menu."
        - ""
        - "&#B8FFF2» Left click: Go back"

version: '1'
```


# hooks.yml

***

```yaml
hooks:
  PlaceholderAPI:
    enabled: true
    placeholders:
      # Returned by any placeholder that has no value to show.
      empty: "---"
      # Seconds between rotations of %quests_current_name% / %quests_current_description%
      # when a player has more than one ongoing (accepted or active) quest.
      rotate-interval: 5

version: '1'
```


# messages.yml

***

```yaml
prefix: "&#F7556B[Quests]"

messages:
  reload: "%prefix% &aPlugin reloaded."
  no-permission: "%prefix% &cYou don't have permission to do this."
  player-required: "%prefix% &cThis command can only be used by a player."
  player-not-found: "%prefix% &cPlayer not found."
  missing-argument: "%prefix% &cMissing required argument."
  update-available: "%prefix% &aA new version is available! &7(&c{current} &7→ &a{new}&7)"

  level:
    info: |
      &8[&bLevel&8] &f{player}
       &7Level: &a{level}
       &7XP: &b{xp}
       &aCompleted: &f{completed}

    set-success: "%prefix% &aUpdated level for &f{player} &7(Level: &a{level}&7, XP: &b{xp}&7)"
    addxp-success: "%prefix% &aAdded &b{amount} XP &ato &f{player}"
    set-completed-success: "&aSet completed quests for {player} to {amount}"
    set-level-success: "%prefix% &aSet level of &f{player} &ato &e{level}&a."
    add-level-success: "%prefix% &aAdded &e{amount} &alevels to &f{player}&a. &7(now: &e{level}&7)"
    remove-level-success: "%prefix% &aRemoved &e{amount} &alevels from &f{player}&a. &7(now: &e{level}&7)"
    set-xp-success: "%prefix% &aSet XP of &f{player} &ato &b{xp}&a."
    remove-xp-success: "%prefix% &aRemoved &b{amount} XP &afrom &f{player}&a. &7(now: &b{xp}&7)"
    reset-success: "%prefix% &aReset level and XP of &f{player}&a."
    up: "&aYou leveled up to &e{level}&a!"
    up-sound: "minecraft:block.note_block.hat"

  quest:
    already-accepted: "%prefix% &cYou have already accepted this quest."
    already-completed: "%prefix% &cYou have already completed this quest."
    already-active: "&cThis quest is already in progress!"
    not-accepted: "&cYou must accept this quest first!"
    not-loaded: "&cYour data is still loading, please wait..."
    daily-reminder:
      - "&eYou have unclaimed daily quests!"
      - "&7Open the quest board with &f/quests board"

    accept:
      success: "%prefix% &aQuest accepted."
      fail: "%prefix% &cFailed to accept quest."
      conditions-failed: "%prefix% &cYou do not meet the requirements for this quest."
      max-reached: "%prefix% &cYou cannot accept more quests! &7(max: {max})"

    start:
      success: "%prefix% &aQuest started."
      fail: "%prefix% &cCannot start this quest."
      max-reached: "%prefix% &cYou cannot have more active quests! &7(max: {max})"

    force:
      give-success: "%prefix% &aForce-gave quest &f{quest_name} &ato &f{player}&a."
      start-success: "%prefix% &aForce-started quest &f{quest_name} &afor &f{player}&a."
      complete-success: "%prefix% &aForce-completed quest &f{quest_name} &afor &f{player}&a."
      fail: "%prefix% &cCould not force quest &f{quest} &cfor &f{player}&c. &7(unknown quest or already held)"

    expiring: "&eYour quest &f{quest} &eis running out! &7({time}) &8[{percent}% left]"
    expiring-sound: "minecraft:block.note_block.hat"
    expired: "&cYour quest &f{quest} &chas expired!"
    expired-sound: "minecraft:entity.villager.no"

  time:
    day: "day"
    day-plural: "days"
    hour: "hour"
    hour-plural: "hours"
    minute: "minute"
    minute-plural: "minutes"
    second: "second"
    second-plural: "seconds"

    short:
      day: "d"
      hour: "h"
      minute: "m"
      second: "s"

version: '1'
```


# quests.yml

***

```yaml
quests:
  beginner_miner:
    display:
      name: "&#B8FFF2&lBeginner Miner"
      material: AMETHYST_SHARD
      custom-model-data: 358

    level-required: 0

    objectives:
      move:
        name: "&#7CF6FF&lFirst Steps"
        description:
          - "&#C7D0D9Explore the world and get familiar"
          - "&#C7D0D9with your surroundings."
          - ""
          - "&#8A8F98Progress: &#FFFFFF{progress}&#8A8F98/&#FFFFFF{required}"
        trigger: move
        target: any
        required: 200

      stone:
        name: "&#D3DBE3&lStone Veins"
        description:
          - "&#C7D0D9Mine stone blocks to gather"
          - "&#C7D0D9your first resources."
          - ""
          - "&#8A8F98Progress: &#FFFFFF{progress}&#8A8F98/&#FFFFFF{required}"
        trigger: block_break
        target: STONE
        required: 64

      craft_pickaxe:
        name: "&#FFD86E&lFirst Upgrade"
        description:
          - "&#C7D0D9Craft a stone pickaxe and"
          - "&#C7D0D9prepare for deeper mining."
          - ""
          - "&#8A8F98Progress: &#FFFFFF{progress}&#8A8F98/&#FFFFFF{required}"
        trigger: craft_item
        target: STONE_PICKAXE
        required: 1

    rewards:
      - type: message
        value: "&#B8FFF2You learned the basics of mining."
      - type: command
        value: give %player% iron_pickaxe 1

    accept-expire: -1
    active-expire: 1800

  monster_hunter:
    display:
      name: "&#FF6B6B&lMonster Hunter"
      material: MACE

    level-required: 0

    objectives:
      deal_damage:
        name: "&#FF9A8B&lCombat Training"
        description:
          - "&#C7D0D9Deal damage to hostile mobs"
          - "&#C7D0D9and prove your strength."
          - ""
          - "&#8A8F98Progress: &#FFFFFF{progress}&#8A8F98/&#FFFFFF{required}"
        trigger: deal_damage
        target: any
        required: 200

      zombies:
        name: "&#8DFFB3&lRotten Threat"
        description:
          - "&#C7D0D9Defeat zombies before they"
          - "&#C7D0D9overrun the area."
          - ""
          - "&#8A8F98Progress: &#FFFFFF{progress}&#8A8F98/&#FFFFFF{required}"
        trigger: kill_entity
        target: ZOMBIE
        required: 15

      skeletons:
        name: "&#D3DBE3&lBone Collector"
        description:
          - "&#C7D0D9Hunt skeletons and survive"
          - "&#C7D0D9their ranged attacks."
          - ""
          - "&#8A8F98Progress: &#FFFFFF{progress}&#8A8F98/&#FFFFFF{required}"
        trigger: kill_entity
        target: SKELETON
        required: 10

    rewards:
      - type: message
        value: "&#FF9A8BYou proved yourself in combat."
      - type: command
        value: eco give %player% 500

    accept-expire: 600
    active-expire: 1800

  explorer:
    display:
      name: "&#7CF6FF&lExplorer"
      material: RECOVERY_COMPASS

    level-required: 0

    objectives:
      travel:
        name: "&#7CF6FF&lOpen Trails"
        description:
          - "&#C7D0D9Travel across the world"
          - "&#C7D0D9and discover new places."
          - ""
          - "&#8A8F98Progress: &#FFFFFF{progress}&#8A8F98/&#FFFFFF{required}"
        trigger: move
        target: any
        required: 800

      interact:
        name: "&#FFD86E&lHidden Supplies"
        description:
          - "&#C7D0D9Open chests and search"
          - "&#C7D0D9for useful supplies."
          - ""
          - "&#8A8F98Progress: &#FFFFFF{progress}&#8A8F98/&#FFFFFF{required}"
        trigger: interact_block
        target: CHEST
        required: 3

      eat:
        name: "&#FF9A8B&lFood Break"
        description:
          - "&#C7D0D9Eat cooked beef to stay"
          - "&#C7D0D9ready for the journey."
          - ""
          - "&#8A8F98Progress: &#FFFFFF{progress}&#8A8F98/&#FFFFFF{required}"
        trigger: consume
        target: COOKED_BEEF
        required: 5

      fish:
        name: "&#8FA3B8&lQuiet Waters"
        description:
          - "&#C7D0D9Catch fish and take a"
          - "&#C7D0D9moment by the water."
          - ""
          - "&#8A8F98Progress: &#FFFFFF{progress}&#8A8F98/&#FFFFFF{required}"
        trigger: fish
        target: any
        required: 3

    rewards:
      message:
        type: message
        value: '&#FF9A8BYou proved yourself in combat.'
      money:
        type: command
        display-name: '&a$500'
        value: eco give %player% 500

    accept-expire: -1
    active-expire: 3600

version: '1'
```


# Features

***

{% content-ref url="/pages/a3pxVY7VYNpW7ySak6MG" %}
[config.yml](/premium-products/mc-tycoonhoe/config-files/config.yml)
{% endcontent-ref %}


# Create a Quest

All quests are defined in `quests.yml`. Every quest is a section under the top-level `quests:` key, and the section name is the quest ID (used in commands, placeholders and storage — pick something short and lowercase, like `beginner_miner`).

You don't need to touch any code. Create the section, run `/quests reload`, and the quest is live.

### A complete example <a href="#a-complete-example" id="a-complete-example"></a>

```yaml
quests:
  beginner_miner:
    display:
      name: "&#B8FFF2&lBeginner Miner"
      material: AMETHYST_SHARD
      custom-model-data: 358

    level: 1
    daily: true

    objectives:
      stone:
        name: "&#D3DBE3&lStone Veins"
        description:
          - "&#C7D0D9Mine stone blocks to gather"
          - "&#C7D0D9your first resources."
          - ""
          - "&#8A8F98Progress: &#FFFFFF{progress}&#8A8F98/&#FFFFFF{required}"
        trigger: block_break
        target: STONE
        required: 64

      craft_pickaxe:
        name: "&#FFD86E&lFirst Upgrade"
        description:
          - "&#C7D0D9Craft a stone pickaxe."
        trigger: craft_item
        target: STONE_PICKAXE
        required: 1

    rewards:
      - type: message
        value: "&#B8FFF2You learned the basics of mining."
      - type: command
        value: give %player% iron_pickaxe 1

    accept-expire: -1
    active-expire: 1800
```

This quest asks the player to mine 64 stone and craft a stone pickaxe. Once both objectives are done, the rewards run automatically.

### Quest options <a href="#quest-options" id="quest-options"></a>

| Key             | Description                                                                                                                            | Default |
| --------------- | -------------------------------------------------------------------------------------------------------------------------------------- | ------- |
| `display`       | How the quest looks in the quest board GUI (see below).                                                                                | –       |
| `level`         | The quest level. The daily board only offers quests within `level-range` (set in `config.yml`) of the player's own level.              | `1`     |
| `daily`         | Whether the quest can appear on the daily quest board. Set to `false` for quests you only hand out manually (e.g. via admin commands). | `true`  |
| `objectives`    | The tasks the player has to complete. At least one is required.                                                                        | –       |
| `conditions`    | Extra requirements checked when the player tries to accept the quest.                                                                  | none    |
| `rewards`       | What the player gets when every objective is complete.                                                                                 | none    |
| `accept-expire` | Seconds the player has to **start** the quest after accepting it. `-1` means no limit.                                                 | `-1`    |
| `active-expire` | Seconds the player has to **finish** the quest once it becomes active. `-1` means no limit.                                            | `-1`    |

{% hint style="info" %}
Both expire values are in **seconds**. `active-expire: 1800` gives the player 30 minutes to finish. Players get warnings as the timer runs down — configurable under `quests.expire-warning` in `config.yml`.
{% endhint %}

#### Display <a href="#display" id="display"></a>

The `display` section controls the item shown for the quest in the board GUI:

```yaml
display:
  name: "&#FF6B6B&lMonster Hunter"
  material: MACE
  custom-model-data: 358   # optional, for resource pack icons
```

`name` supports legacy color codes (`&a`) and hex colors (`&#FF6B6B`). `material` is any [Bukkit Material](https://jd.papermc.io/paper/1.21/org/bukkit/Material.html) name.

### Objectives <a href="#objectives" id="objectives"></a>

Each objective is a named section under `objectives:`. The section name (e.g. `stone`) is the objective ID — it's used to track progress, so don't rename it after players have started the quest.

```yaml
objectives:
  zombies:
    name: "&#8DFFB3&lRotten Threat"
    description:
      - "&#C7D0D9Defeat zombies before they"
      - "&#C7D0D9overrun the area."
      - ""
      - "&#8A8F98Progress: &#FFFFFF{progress}&#8A8F98/&#FFFFFF{required}"
    trigger: kill_entity
    target: ZOMBIE
    required: 15
```

| Key           | Description                                                                                                                   |
| ------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `trigger`     | What kind of action counts (see the trigger list below).                                                                      |
| `target`      | What exactly the action must involve — a block, item, entity, world, etc. Depends on the trigger. Some triggers accept `any`. |
| `required`    | How many times the action must happen (or the total amount, for damage/distance/XP based triggers).                           |
| `name`        | Objective name shown in GUIs and completion messages.                                                                         |
| `description` | Lore lines shown in GUIs. `{progress}` and `{required}` are replaced with the player's live progress.                         |

A quest is complete when **all** of its objectives are complete. Objectives progress in parallel — there's no fixed order.

#### Triggers <a href="#triggers" id="triggers"></a>

**Vanilla triggers** (no extra plugin needed):

| Trigger                | Counts when the player...               | `target`                            |
| ---------------------- | --------------------------------------- | ----------------------------------- |
| `block_break`          | breaks a block                          | block material, e.g. `STONE`        |
| `place_block`          | places a block                          | block material                      |
| `interact_block`       | right-clicks a block                    | block material, e.g. `CHEST`        |
| `kill_entity`          | kills a mob                             | entity type, e.g. `ZOMBIE`          |
| `deal_damage`          | deals damage (progress = damage dealt)  | `any`                               |
| `take_damage`          | takes damage (progress = damage taken)  | `any`                               |
| `move`                 | walks (progress = blocks traveled)      | `any`                               |
| `move_while_sprinting` | sprints                                 | `any`                               |
| `move_while_sneaking`  | sneaks while moving                     | `any`                               |
| `move_while_flying`    | flies                                   | `any`                               |
| `move_while_swimming`  | swims                                   | `any`                               |
| `fish`                 | catches something while fishing         | `any`                               |
| `craft_item`           | crafts an item                          | item material, e.g. `STONE_PICKAXE` |
| `smelt_item`           | takes an item out of a furnace          | item material or `any`              |
| `consume`              | eats or drinks an item                  | item material, e.g. `COOKED_BEEF`   |
| `change_world`         | switches world                          | world name or `any`                 |
| `gain_exp`             | gains vanilla XP (progress = XP gained) | `any`                               |
| `gain_quest_xp`        | gains quest XP                          | `any`                               |
| `level_up`             | levels up in the quest leveling system  | `any`                               |

{% hint style="warning" %}
`target` values for vanilla triggers must be exact material/entity names (`IRON_ORE`, `SKELETON`, ...). A typo means the objective simply never progresses — no error is thrown.
{% endhint %}

### Rewards <a href="#rewards" id="rewards"></a>

Rewards run once, when the last objective is completed. They can be written as a list:

```yaml
rewards:
  - type: message
    value: "&#B8FFF2Well done!"
  - type: command
    value: eco give %player% 500
```

or as named sections, which lets you add a `display-name` (shown in GUIs instead of the raw value):

```yaml
rewards:
  money:
    type: command
    display-name: "&a$500"
    value: eco give %player% 500
  bonus_xp:
    type: quest_xp
    value: 250
```

Available reward types:

| Type       | `value`                                   | What it does                                                               |
| ---------- | ----------------------------------------- | -------------------------------------------------------------------------- |
| `message`  | text (colors supported)                   | Sends a chat message to the player.                                        |
| `command`  | console command, `%player%` = player name | Runs the command from console.                                             |
| `item`     | `MATERIAL:amount`, e.g. `DIAMOND:3`       | Puts the item in the player's inventory.                                   |
| `xp`       | number                                    | Gives vanilla experience.                                                  |
| `quest_xp` | number                                    | Gives quest XP (multiplied by the player's premium XP multiplier, if any). |

The `command` type is the most flexible — anything a console command can do (economy, crates, permissions, custom items) can be a reward.

### Conditions <a href="#conditions" id="conditions"></a>

Conditions are checked when a player tries to **accept** the quest. If any condition fails, the quest can't be accepted.

```yaml
conditions:
  - type: permission
    value: quests.vip
  - type: world
    value: world_nether
```

| Type         | `value`         | Requirement                           |
| ------------ | --------------- | ------------------------------------- |
| `permission` | permission node | The player must have this permission. |
| `world`      | world name      | The player must be in this world.     |

### Applying your changes <a href="#applying-your-changes" id="applying-your-changes"></a>

After editing `quests.yml`, run:

```
/quests reload
```

Quests already accepted by players keep running with the definition they were started with; new accepts use the updated config.

{% hint style="info" %}
You can hand out any quest directly with `/quests force give <player> <quest>` or `/quests force start <player> <quest>` (permission `mcquests.admin.force`), even quests with `daily: false` that never appear on the board — handy for testing a new quest before players see it.
{% endhint %}


# Daily Board

The daily board is each player's personal quest selection for the day. Every player gets their own randomized set of quests, picked from your quest pool based on their level. The board is saved to the database, so it survives restarts and relogs — a player keeps the same board until the daily reset (or until they reroll it).

Players open the board with `/quests`.

### How quests are picked <a href="#how-quests-are-picked" id="how-quests-are-picked"></a>

When a player's board is generated, the plugin:

1. Collects every quest with `daily: true` whose `level` is within `level-range` of the player's level.
2. Randomly picks quests from that pool, one by one, until the board is full. The pick is **weighted** — quests closer to the player's level are more likely to be chosen, but anything in range can appear.
3. Saves the board with an expiry timestamp set to the next daily reset.

A quest can only appear once per board. If the pool is smaller than the board size, the player simply gets fewer quests.

{% hint style="info" %} Quests with `daily: false` in `quests.yml` never appear on the board. Use that for quests you only hand out with `/quests force give`. {% endhint %}

### Configuration <a href="#configuration" id="configuration"></a>

Everything lives under `quests.daily-board` in `config.yml`:

```yaml
quests:
  daily-board:
    base: 5
    per-level: 5
    level-range: 15
    reset-time: "04:00"
    timezone: "Europe/Budapest"
```

| Key           | Description                                                                                                                                     |
| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `base`        | How many quests every player gets on their board.                                                                                               |
| `per-level`   | Grants one extra board slot every X levels. With `per-level: 5`, a level 12 player gets 2 extra slots (`12 / 5 = 2`). Set to `0` to disable.    |
| `level-range` | How far a quest's `level` may be from the player's level to be eligible. With `range: 15`, a level 20 player can get quests from level 5 to 35. |
| `reset-time`  | When boards expire and regenerate, in 24-hour `HH:mm` format.                                                                                   |
| `timezone`    | IANA timezone for the reset time (e.g. `Europe/Budapest`, `America/New_York`). Leave empty to use the server's timezone.                        |

#### How the reset works <a href="#how-the-reset-works" id="how-the-reset-works"></a>

There's no server-wide reset task. Each board stores its own expiry time; when a player opens the board after the reset time has passed, a fresh one is generated on the spot. The time remaining is shown in the GUI title via the `{reset}` placeholder.

#### Related limits <a href="#related-limits" id="related-limits"></a>

These aren't board settings, but they shape how players interact with it (`config.yml`):

```yaml
quests:
  limits:
    max-accepted:
      base: 3
      per-level: 10
    max-active:
      base: 1
      per-level: 20
```

`max-accepted` caps how many quests a player can hold at once, and `max-active` caps how many can progress at the same time. Both grow with level the same way board slots do (`base + level / per-level`).

### Rerolling <a href="#rerolling" id="rerolling"></a>

The board GUI has a refresh button that regenerates the player's board immediately with a new random selection. By default it's free. To charge for it, enable `refresh-cost` under `quest-board` in `guis.yml`:

```yaml
quest-board:
  refresh-cost:
    enabled: true
    placeholder: "%vault_eco_balance%"
    cost: 1000.0
    take-command: "eco take %player% 1000"
    sounds:
      success: "entity.experience_orb.pickup"
      error: "entity.villager.no"
    messages:
      not-enough: "&#FF6B6BYou don't have enough money to reroll your quests."
      success: "&#B8FFF2Your quests have been rerolled for &#FFFFFF{cost}&#B8FFF2."
```

| Key            | Description                                                     |
| -------------- | --------------------------------------------------------------- |
| `placeholder`  | A PlaceholderAPI placeholder that returns the player's balance. |
| `cost`         | The minimum balance required to reroll.                         |
| `take-command` | Console command that actually withdraws the money.              |

{% hint style="warning" %}
The paid reroll requires **PlaceholderAPI** plus whatever plugin provides the balance placeholder (e.g. Vault). Keep `cost` and `take-command` in sync — the plugin checks the balance against `cost` but takes money with the command.
{% endhint %}

Rerolling replaces the whole board, including quests the player hasn't finished yet. Already accepted quests keep running.

### Premium bonuses <a href="#premium-bonuses" id="premium-bonuses"></a>

Players with the `mcquests.premium` permission get the bonuses defined in `config.yml`:

```yaml
premium:
  bonus:
    max-accepted: 3
    max-active: 1
    daily-board: 2

  multipliers:
    xp: 1.25
    reward: 1.5
```

`daily-board: 2` means premium players see 2 more quests on their board. Premium players also get a different GUI title (`title-premium` in `guis.yml`) and the multipliers apply to their quest XP and rewards.

### Customizing the GUI <a href="#customizing-the-gui" id="customizing-the-gui"></a>

The whole board menu is configured under `quest-board` in `guis.yml`:

```yaml
quest-board:
  title: "<dark_gray>Quest Board ({reset})"
  title-premium: "<dark_gray>Premium Quest Board ({reset})"
  size: 54

  quest-slots: [20, 21, 22, 23, 24, 29, 30, 31, 32, 33]

  quest-template:
    material: TRIAL_KEY
    name: "&#B8FFF2&l{name}"
    lore:
      - " &#8A8F98◆ Status: {status}"
      - "&#7CF6FF&lOBJECTIVES"
      - "{objectives}"
      - "{action}"
```

The important parts:

* **`quest-slots`** — the inventory slots where daily quests appear. This also caps how many quests are visible: if a player's board size is larger than the number of slots, the extra quests aren't shown, so add slots if you raise the board size.
* **`quest-template`** — the item used for every quest that has no `display` section of its own. Quests with a `display` in `quests.yml` use their own icon, but always take the template's lore.
* **`formats`** — the text snippets used to fill the template: status lines, objective/reward/condition lines, time limit lines and the click hints.

Template lore placeholders: `{name}`, `{status}`, `{objectives}`, `{conditions}`, `{rewards}`, `{time}` and `{action}`. The list placeholders (`{objectives}`, `{rewards}`, `{conditions}`) expand to one line per entry using the matching `formats` entry, with live progress numbers for objectives.

Sounds for opening, accepting, errors and rerolling are under `quest-board.sounds`.

### Accepting quests from the board <a href="#accepting-quests-from-the-board" id="accepting-quests-from-the-board"></a>

Clicking a quest on the board accepts it. The plugin checks, in order:

1. The quest isn't already completed today or already accepted.
2. The player is below their `max-accepted` limit.
3. The quest's `conditions` (permission, world) pass.

Completed board quests stay visible with the `completed` status until the reset, so players can see what they've already done today.


# Premium Pass

The plugin has a built-in two-tier pass system: every player is **Free** by default, and players with the `mcquests.premium` permission are **Premium**. Premium players get more quests, more slots and better multipliers — how much better is entirely up to your config.

### Granting premium <a href="#granting-premium" id="granting-premium"></a>

There is no command or purchase system inside the plugin — premium is just a permission node:

```
mcquests.premium
```

Because it's a plain permission, it plugs into anything: rank purchases from your store, temporary passes (`/lp user Steve permission settemp mcquests.premium true 30d`), rank inheritance, and so on.

The check is live — as soon as the permission is added or removed, the player's bonuses change. No restart or reload needed.

### What premium players get <a href="#what-premium-players-get" id="what-premium-players-get"></a>

Everything is configured under the `premium` section in `config.yml`:

```yaml
premium:
  bonus:
    max-accepted: 3
    max-active: 1
    daily-board: 2

  multipliers:
    xp: 1.25
    reward: 1.5
```

#### Bonuses <a href="#bonuses" id="bonuses"></a>

Bonuses are **added on top** of what the player already has from the base values and their level (see [Daily Board](/premium-products/quests/features/daily-board) for how those grow).

| Key            | Description                                        |
| -------------- | -------------------------------------------------- |
| `max-accepted` | Extra quests the player can hold at the same time. |
| `max-active`   | Extra quests that can progress at the same time.   |
| `daily-board`  | Extra quests on the player's daily board.          |

Example: with `quests.limits.max-accepted.base: 3` and a premium bonus of `3`, a fresh premium player can hold 6 quests while a free player holds 3.

#### Multipliers <a href="#multipliers" id="multipliers"></a>

| Key      | Description                                                                                                                                                                                                                          |
| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `xp`     | Multiplies all quest XP earned from `quest_xp` rewards. With `1.25`, a reward of `value: 200` gives a premium player 250 XP.                                                                                                         |
| `reward` | The premium reward multiplier. It is shown to players (GUIs, `%quests_reward_multiplier%`), but reward values themselves are not automatically scaled — `command`, `item` and other reward types run as written in the quest config. |

{% hint style="info" %}
The `xp` multiplier only applies to quest XP (the plugin's own leveling system), not to vanilla XP given by the `xp` reward type.
{% endhint %}

### Premium in the GUI <a href="#premium-in-the-gui" id="premium-in-the-gui"></a>

The quest board shows the player's tier in a few places, all configurable in `guis.yml`:

* **`title-premium`** — premium players get this menu title instead of `title`. Leave it empty to use the same title for everyone. Both titles support `{reset}` for the time left until the daily reset.
* **`{pass-type}`** — usable in the board's item names and lore (the default player head uses it), shows `Premium` or `Free`.
* **`{daily-board-size}`, `{max-accepted}`, `{max-active}`, `{xp-multiplier}`** — these already include the premium bonuses, so premium players see their real limits.

```yaml
quest-board:
  title: "<dark_gray>Quest Board ({reset})"
  title-premium: "<dark_gray>Premium Quest Board ({reset})"
```

### Premium-only quests <a href="#premium-only-quests" id="premium-only-quests"></a>

There's no `premium: true` flag on quests — instead, use a permission condition:

```yaml
conditions:
  - type: permission
    value: mcquests.premium
```

The quest still shows up on the board for everyone in the level range, but only premium players can accept it. Free players clicking it get the conditions-failed message, which makes it a nice upsell spot.


# Level System

The plugin has its own leveling system, completely separate from vanilla XP. Every player starts at level 1 and levels up by earning **quest XP**. The level is more than a number — it decides how many quests a player can hold, how big their daily board is, and which quests the board offers them.

### Earning XP <a href="#earning-xp" id="earning-xp"></a>

Quest XP comes from the `quest_xp` reward type. Add it to any quest and the player earns XP on completion:

```yaml
rewards:
  - type: quest_xp
    value: 250
```

Premium players earn more from the same quest — their XP multiplier (`premium.multipliers.xp`) is applied automatically. Admins can also grant XP directly with `/level addxp` (see below).

### The level curve <a href="#the-level-curve" id="the-level-curve"></a>

How much XP a level requires is controlled by two values in `config.yml`:

```yaml
leveling:
  base-xp: 100
  scale: 1.5
```

The formula for the XP needed to go from a level to the next one:

```
required XP = base-xp × level ^ scale
```

With the defaults, that looks like this:

| Level   | XP to next level |
| ------- | ---------------- |
| 1 → 2   | 100              |
| 2 → 3   | \~283            |
| 5 → 6   | \~1,118          |
| 10 → 11 | \~3,162          |
| 20 → 21 | \~8,944          |
| 50 → 51 | \~35,355         |

* **`base-xp`** shifts the whole curve up or down — double it and every level costs twice as much.
* **`scale`** controls how steep it gets. `1.0` is linear (level 10 costs 10× level 1), higher values make high levels progressively more expensive. Values between `1.2` and `1.8` are the practical range for most servers.

Leftover XP carries over: if a player needs 100 XP and earns 250, they level up and keep 150 toward the next level. A single large XP grant can trigger several level-ups at once — each level fires its own message, sound and rewards.

### Level-up rewards <a href="#level-up-rewards" id="level-up-rewards"></a>

When a player levels up, three things run, all configured under `leveling.level-up` in `config.yml`:

```yaml
leveling:
  level-up:
    commands:
      - "eco give {player} 50"

    rewards:
      default:
        commands:
          - "eco give {player} 100"

      levels:
        5:
          commands:
            - "give {player} diamond 1"
        10:
          commands:
            - "crate give {player} epic 1"
        20:
          commands:
            - "lp user {player} permission set quests.vip"
```

1. **The level-up message and sound** — configured in `messages.yml`.
2. **`commands`** — run on *every* level-up. Good for a small flat bonus.
3. **`rewards`** — either the milestone entry for the reached level (`levels.5`, `levels.10`, ...) or, if the level has no entry, the `default` one. A milestone **replaces** the default for that level, it doesn't stack on top of it.

All commands run from console and support two placeholders: `{player}` (player name) and `{level}` (the level just reached).

{% hint style="warning" %}
Leveling commands use `{player}`, not `%player%` — that syntax belongs to quest `command` rewards in `quests.yml`. Mixing them up leaves the placeholder unreplaced in the command.
{% endhint %}

### What the level affects <a href="#what-the-level-affects" id="what-the-level-affects"></a>

A player's level feeds back into almost everything:

| System                 | Effect                                                                                                                                 |
| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| Daily board size       | `quests.daily-board.per-level` grants extra board slots as the level grows.                                                            |
| Daily board pool       | Only quests within `level-range` of the player's level can appear, and quests closer to their level are picked more often.             |
| Accepted/active limits | `quests.limits.max-accepted.per-level` and `max-active.per-level` raise the caps with level.                                           |
| Quest objectives       | The `level_up` and `gain_quest_xp` triggers let quests react to the leveling system itself ("reach a new level", "earn 500 quest XP"). |

See the [Daily Board](/premium-products/quests/features/daily-board) page for the exact math behind the per-level bonuses.

### Showing the level <a href="#showing-the-level" id="showing-the-level"></a>

* In the quest board GUI, the player head uses `{level}`, `{xp}`, `{xp-needed}` and `{progress}` (percentage toward the next level).
* Everywhere else, use the PlaceholderAPI placeholders — `%quests_level%`, `%quests_level_formatted%`, `%quests_xp%` — covered on the [Placeholders](file:///C:/Users/KomPhone/IdeaProjects/mc-Quests/docs/placeholders.md) page, including the level formatting rules (`MAX` labels, custom glyphs).

### Admin commands <a href="#admin-commands" id="admin-commands"></a>

All level commands require the `mcquests.admin.level` permission and work on offline players too:

| Command                                 | What it does                                                                                       |
| --------------------------------------- | -------------------------------------------------------------------------------------------------- |
| `/level info [player]`                  | Shows level, XP and completed quest count.                                                         |
| `/level set <player> <level> <xp>`      | Sets level and XP in one go.                                                                       |
| `/level setlevel <player> <level>`      | Sets the level, keeps the XP.                                                                      |
| `/level addlevel <player> <amount>`     | Adds levels (can't go below 1).                                                                    |
| `/level removelevel <player> <amount>`  | Removes levels (can't go below 1).                                                                 |
| `/level setxp <player> <xp>`            | Sets the XP within the current level.                                                              |
| `/level addxp <player> <amount>`        | Adds XP — this goes through the normal XP pipeline, so it can trigger level-ups and their rewards. |
| `/level removexp <player> <amount>`     | Removes XP (can't go below 0).                                                                     |
| `/level setcompleted <player> <amount>` | Sets the completed-quest counter.                                                                  |
| `/level reset <player>`                 | Back to level 1 with 0 XP. The completed counter is kept.                                          |

{% hint style="info" %}
`/level addxp` is the only command that triggers level-ups, messages and rewards. The `set`/`setlevel`/`addlevel` commands change the values silently — use them for corrections, not for granting progress.
{% endhint %}


# Supported Plugins

***

Supported Plugins list:

```yaml
- mc-ItemStorage
- ProtocolLib
- ModelEngine
- PlaceholderAPI
- mc-Friends
- AxBoosters
- BattlePass
- mc-TycoonPet
- mc-PowerUp
```


# PlaceholderAPI

The plugin support PlaceholderAPI and have different placeholders.

With [PlaceholderAPI](https://www.spigotmc.org/resources/placeholderapi.6245/) installed, the plugin registers the `quests` expansion automatically — no ecloud download needed. You can use these placeholders in any plugin that supports PlaceholderAPI.

All placeholders start with `%quests_`.

### Leveling <a href="#leveling" id="leveling"></a>

| Placeholder                | Value                                                                    |
| -------------------------- | ------------------------------------------------------------------------ |
| `%quests_level%`           | The player's quest level as a plain number.                              |
| `%quests_level_formatted%` | The level after applying your display rules (see Formatted level below). |
| `%quests_xp%`              | The player's current quest XP.                                           |
| `%quests_completed%`       | Total number of quests the player has ever completed.                    |

#### Formatted level <a href="#formatted-level" id="formatted-level"></a>

`%quests_level_formatted%` runs the raw level through the `placeholders.level` section of `config.yml`:

```yaml
placeholders:
  level:
    placeholder-condition:
      enabled: true
      levels: '%nexo_level_<player_level>%'

    overrides:
      "100": "&6MAX"
      "50": "&eVIP"
```

The lookup order is:

1. **`overrides`** — if the player's exact level is listed here, that text is returned. Handy for a `MAX` label at the level cap or special names at milestone levels.
2. **`placeholder-condition`** — if enabled, the level is inserted into the `levels` template in place of `<player_level>`, and the result is parsed as a placeholder again. The example above turns level 7 into `%nexo_level_7%`, which lets a resource-pack font plugin like Nexo render the level as a custom glyph.
3. Otherwise the plain number is returned.

### Player quests <a href="#player-quests" id="player-quests"></a>

| Placeholder                    | Value                                                                   |
| ------------------------------ | ----------------------------------------------------------------------- |
| `%quests_quests_total%`        | How many quests the player currently holds (accepted + active).         |
| `%quests_quests_accepted%`     | Quests the player has accepted but not started yet.                     |
| `%quests_quests_active%`       | Quests currently in progress.                                           |
| `%quests_quests_max_accepted%` | The player's accepted-quest limit (level and premium bonuses included). |
| `%quests_quests_max_active%`   | The player's active-quest limit (level and premium bonuses included).   |

{% hint style="info" %}
**Accepted** means the player picked the quest up from the board; **active** means they've started it and objectives are progressing. The two limits are configured under `quests.limits` in `config.yml`.
{% endhint %}

### Current quest <a href="#current-quest" id="current-quest"></a>

These two are made for scoreboards — they show what the player is working on right now:

| Placeholder                    | Value                                                                                                            |
| ------------------------------ | ---------------------------------------------------------------------------------------------------------------- |
| `%quests_current_name%`        | The display name of one of the player's ongoing quests.                                                          |
| `%quests_current_description%` | The description of that quest's most-progressed objective, with `{progress}` and `{required}` already filled in. |

If the player has **more than one** ongoing quest, the two placeholders rotate through them in sync, switching every few seconds. The interval is set in `hooks.yml`:

```yaml
hooks:
  PlaceholderAPI:
    placeholders:
      # Returned by any placeholder that has no value to show.
      empty: "---"
      # Seconds between rotations of %quests_current_name% / %quests_current_description%
      # when a player has more than one ongoing (accepted or active) quest.
      rotate-interval: 5
```

If the player has no ongoing quest, both return the `empty` text (`---` by default). The same fallback is used by every placeholder that has nothing to show.

### Daily board <a href="#daily-board" id="daily-board"></a>

| Placeholder            | Value                                                                                                                                                              |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `%quests_daily_size%`  | How many quests the player's daily board holds (level and premium bonuses included).                                                                               |
| `%quests_daily_reset%` | Time left until the player's board resets, formatted (e.g. `5h 23m`). Returns the `empty` text until the player has opened their board at least once this session. |

### Premium <a href="#premium" id="premium"></a>

| Placeholder                  | Value                                                                                                                             |
| ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| `%quests_type%`              | `premium` or `free` — lowercase, meant for comparisons in other plugins' conditions.                                              |
| `%quests_type_formatted%`    | `Premium` or `Free` — display text. Override it in `messages.yml` under `placeholders.type.premium` and `placeholders.type.free`. |
| `%quests_xp_multiplier%`     | The player's quest XP multiplier (e.g. `1.25`).                                                                                   |
| `%quests_reward_multiplier%` | The player's reward multiplier.                                                                                                   |

See the [Premium Pass](/premium-products/quests/features/premium-pass) page for how these values are built up.


# CustomFishing

When [CustomFishing](https://polymart.org/resource/customfishing.2723) is installed, three fishing triggers become available. Detection is automatic.

| Trigger                           | Counts when the player...                | Progress          |
| --------------------------------- | ---------------------------------------- | ----------------- |
| `customfishing_fish`              | successfully catches CustomFishing loot  | amount caught     |
| `customfishing_market_sell`       | sells in the CustomFishing market        | money earned      |
| `customfishing_participate_event` | is in a fishing competition when it ends | 1 per competition |

### `customfishing_fish` <a href="#customfishing_fish" id="customfishing_fish"></a>

Counts successful catches only — failed minigames don't progress the objective. The `target` is a CustomFishing **loot ID** from your loot configs, or `any`:

```yaml
objectives:
  rare_catch:
    name: "&#7CF6FF&lLegend of the Lake"
    description:
      - "&#C7D0D9Catch the golden koi that"
      - "&#C7D0D9lives in the crater lake."
    trigger: customfishing_fish
    target: golden_koi
    required: 1
```

Use `any` together with a higher `required` for volume quests — progress counts the caught amount, so multi-catches count fully.

### `customfishing_market_sell` <a href="#customfishing_market_sell" id="customfishing_market_sell"></a>

Progress is the total sale price, so `required` is a money amount. The `target` must be `any`:

```yaml
objectives:
  fish_merchant:
    name: "&#FFD86E&lFish Merchant"
    trigger: customfishing_market_sell
    target: any
    required: 2500
```

This only tracks the CustomFishing market — selling fish through other shops counts toward [ShopGUIPlus](file:///C:/Users/KomPhone/IdeaProjects/mc-Quests/docs/integrations/shopguiplus.md) triggers instead.

### `customfishing_participate_event` <a href="#customfishing_participate_event" id="customfishing_participate_event"></a>

Evaluated when a fishing competition **ends**. The `target` decides what counts:

* `any` — the player took part in the competition.
* `first` (or any other value) — the player finished **first**.

```yaml
objectives:
  competitor:
    name: "&#8DFFB3&lFriendly Rivalry"
    trigger: customfishing_participate_event
    target: any
    required: 3

  champion:
    name: "&#FFD86E&lTournament Champion"
    trigger: customfishing_participate_event
    target: first
    required: 1
```

{% hint style="info" %}
Competition quests work best with a longer `active-expire` (or none at all) — players can only progress them when a competition actually runs.
{% endhint %}


# EssentialsX

When [EssentialsX](https://essentialsx.net/) provides your economy, the `gain_money` trigger becomes available. Detection is automatic.

| Trigger      | Counts when the player...          | Progress          |
| ------------ | ---------------------------------- | ----------------- |
| `gain_money` | balance increases, from any source | the amount gained |

Unlike [ShopGUIPlus](file:///C:/Users/KomPhone/IdeaProjects/mc-Quests/docs/integrations/shopguiplus.md) `sell_money` (which only counts shop sales), `gain_money` watches the player's Essentials balance directly — job payouts, sell commands, admin grants, anything that raises the balance counts.

The `target` must be `any`:

```yaml
objectives:
  earn:
    name: "&#FFD86E&lFirst Fortune"
    description:
      - "&#C7D0D9Earn money from any source."
      - ""
      - "&#8A8F98Progress: &#FFFFFF{progress}&#8A8F98/&#FFFFFF{required}"
    trigger: gain_money
    target: any
    required: 5000
```

### Good to know <a href="#good-to-know" id="good-to-know"></a>

* **`/pay` doesn't count.** Player-to-player payments are deliberately ignored, so players can't complete money quests by passing the same coins back and forth.
* Progress is counted in whole currency units; decimals are rounded down.
* Only balance **increases** count — losing money never reduces quest progress.


# ExcellentCrates

When [ExcellentCrates](https://spigotmc.org/resources/excellentcrates.48732/) is installed, the `excellentcrates_crate_open` trigger becomes available. Detection is automatic.

| Trigger                      | Counts when the player... | Progress      |
| ---------------------------- | ------------------------- | ------------- |
| `excellentcrates_crate_open` | opens a crate             | 1 per opening |

The `target` is the crate's **ID** (the config/file name in ExcellentCrates, not the display name). Use `any` or `all` to count every crate:

```yaml
objectives:
  lucky_day:
    name: "&#FFD86E&lLucky Day"
    description:
      - "&#C7D0D9Open epic crates and test"
      - "&#C7D0D9your luck."
      - ""
      - "&#8A8F98Progress: &#FFFFFF{progress}&#8A8F98/&#FFFFFF{required}"
    trigger: excellentcrates_crate_open
    target: epic
    required: 3
```

Or, counting any crate:

```yaml
objectives:
  crate_hunter:
    name: "&#7CF6FF&lCrate Hunter"
    trigger: excellentcrates_crate_open
    target: any
    required: 10
```

A crate-open quest pairs nicely with a crate-key reward — a quest that opens crates and pays out a key for a better one gives players a reason to keep both systems running:

```yaml
rewards:
  - type: command
    display-name: "&#FFD86E1x Epic Key"
    value: crates key give %player% epic 1
```


# FancyNpcs

When [FancyNpcs](https://modrinth.com/plugin/fancynpcs) is installed, the `interact_npc` trigger becomes available. Detection is automatic.

| Trigger        | Counts when the player... | Progress          |
| -------------- | ------------------------- | ----------------- |
| `interact_npc` | clicks an NPC             | 1 per interaction |

The `target` is the NPC's **name** — the one you gave it in `/npc create <name>`, not its display name. It's required; there's no `any`.

```yaml
objectives:
  report_back:
    name: "&#7CF6FF&lReport to the Captain"
    description:
      - "&#C7D0D9Find the captain at the docks"
      - "&#C7D0D9and tell him what you saw."
    trigger: interact_npc
    target: captain
    required: 1
```

### Quest chains with NPCs <a href="#quest-chains-with-npcs" id="quest-chains-with-npcs"></a>

This trigger is the building block for classic RPG-style quest flows:

* **Delivery quests** — objective 1: collect items, objective 2: `interact_npc` on the recipient. Since all objectives progress in parallel, tell players the order in the descriptions.
* **Talk-to-X-people quests** — one `interact_npc` objective per NPC, each with `required: 1`.
* **Turn-in endings** — make `interact_npc` the last objective of every story quest, so quests always end at a character instead of in mid-air.

{% hint style="info" %}
Every click counts, and there's no cooldown on the plugin side — with `required: 5`, five quick clicks on the same NPC complete the objective. For "visit 5 different NPCs" quests, use five separate objectives instead of one with `required: 5`.
{% endhint %}


# MythicMobs

When [MythicMobs](https://www.spigotmc.org/resources/mythicmobs.5702/) is installed, three extra triggers become available. Detection is automatic — no config needed, just have MythicMobs enabled when the server starts.

| Trigger             | Counts when the player...            | Progress         |
| ------------------- | ------------------------------------ | ---------------- |
| `kill_mythic_mob`   | kills a MythicMob                    | 1 per kill       |
| `damage_mythic_mob` | damages a MythicMob                  | the damage dealt |
| `signal_mythic_mob` | receives a signal from a mob's skill | 1 per signal     |

### `kill_mythic_mob` <a href="#kill_mythic_mob" id="kill_mythic_mob"></a>

The `target` is the mob's **internal name** — the top-level key from your MythicMobs mob file, not its display name:

```yaml
objectives:
  slay_boss:
    name: "&#FF6B6B&lDragon Slayer"
    trigger: kill_mythic_mob
    target: SkeletalDragon
    required: 1
```

### `damage_mythic_mob` <a href="#damage_mythic_mob" id="damage_mythic_mob"></a>

Progress is the damage dealt, so `required` is a total damage amount, not a hit count. Use the internal name as `target`, or `any` to count damage against every MythicMob:

```yaml
objectives:
  wear_down:
    name: "&#FF9A8B&lSiege Participant"
    trigger: damage_mythic_mob
    target: SkeletalDragon
    required: 500
```

This is great for boss events — every participant can complete the objective, not just whoever lands the killing blow.

### `signal_mythic_mob` <a href="#signal_mythic_mob" id="signal_mythic_mob"></a>

The most flexible of the three: the objective progresses when a MythicMobs skill sends a **signal** to the player. The `target` is the signal name, and it's required — there's no `any`.

In your MythicMobs skill config:

```yaml
Skills:
  - signal{s=BOSS_PHASE2} @PIR{r=30}
```

And in the quest:

```yaml
objectives:
  witness_phase2:
    name: "&#D3DBE3&lSurvived the Frenzy"
    trigger: signal_mythic_mob
    target: BOSS_PHASE2
    required: 1
```

Since signals can be fired from any point of a mob's skill tree (phase changes, mechanics dodged, timed events), this lets quests react to basically anything that happens in a boss fight.


# Nexo

When [Nexo](https://polymart.org/resource/nexo.6901) is installed, two triggers for custom items become available. Detection is automatic.

| Trigger           | Counts when the player...          | Progress       |
| ----------------- | ---------------------------------- | -------------- |
| `nexo_craft_item` | crafts a Nexo item                 | 1 per craft    |
| `nexo_smelt_item` | takes a Nexo item out of a furnace | amount smelted |

The vanilla `craft_item` and `smelt_item` triggers only understand vanilla materials — these two match on the **Nexo item ID** instead, so you can build quests around your custom item tiers.

### `nexo_craft_item` <a href="#nexo_craft_item" id="nexo_craft_item"></a>

The `target` is the Nexo item ID and it's required — there's no `any` (for "craft anything" quests use the vanilla `craft_item` trigger with the item's base material):

```yaml
objectives:
  forge_blade:
    name: "&#FF6B6B&lForge the Ember Blade"
    description:
      - "&#C7D0D9Craft an ember blade at"
      - "&#C7D0D9the workbench."
    trigger: nexo_craft_item
    target: ember_blade
    required: 1
```

### `nexo_smelt_item` <a href="#nexo_smelt_item" id="nexo_smelt_item"></a>

Fires when the smelted result is taken out of the furnace. The `target` is a Nexo item ID or `any`, and progress counts the full amount extracted:

```yaml
objectives:
  smelt_ore:
    name: "&#FFD86E&lMythril Smelter"
    trigger: nexo_smelt_item
    target: mythril_ingot
    required: 16
```

{% hint style="info" %}
Item IDs are the keys from your Nexo item configs (`ember_blade`, not `&cEmber Blade`). A typo means the objective silently never progresses, so test new quests with `/quests force give` before putting them on the board.
{% endhint %}


# ShopGUI+

When [ShopGUIPlus](https://www.spigotmc.org/resources/shopgui-1-8-1-21.6515/) is installed, three shop-based triggers become available. Detection is automatic. Only transactions made through the shop GUI count — trades, other economy plugins and command-based selling don't.

| Trigger      | Counts when the player... | Progress                   |
| ------------ | ------------------------- | -------------------------- |
| `sell_item`  | sells items to the shop   | number of items sold       |
| `buy_item`   | buys items from the shop  | number of items bought     |
| `sell_money` | sells items to the shop   | money earned from the sale |

`sell_item` and `sell_money` fire on the same action — the difference is what they count. Use `sell_item` for "sell 64 wheat" quests and `sell_money` for "earn $10,000 by selling" quests. Sell-all counts too.

### Targets <a href="#targets" id="targets"></a>

All three triggers accept the same `target` values:

* A **material name** (`WHEAT`, `DIAMOND`, ...) — only that item counts.
* **`any`** — every shop transaction counts.
* **`CROPS`** — a built-in group of farm goods, for farming quests without listing every crop:

> `WHEAT`, `CARROT`, `POTATO`, `BEETROOT`, `MELON_SLICE`, `PUMPKIN`, `SUGAR_CANE`, `CACTUS`, `BAMBOO`, `COCOA_BEANS`, `NETHER_WART`, `SWEET_BERRIES`, `GLOW_BERRIES`, `KELP`, `DRIED_KELP`

### Examples <a href="#examples" id="examples"></a>

A farmer quest using the crop group:

```yaml
objectives:
  harvest_sale:
    name: "&#8DFFB3&lMarket Day"
    trigger: sell_item
    target: CROPS
    required: 256
```

A money-target version of the same idea:

```yaml
objectives:
  big_earner:
    name: "&#FFD86E&lBig Earner"
    trigger: sell_money
    target: any
    required: 10000
```

And a buying objective:

```yaml
objectives:
  stock_up:
    name: "&#7CF6FF&lStocking Up"
    trigger: buy_item
    target: ARROW
    required: 128
```

{% hint style="info" %}
`sell_money` progress is counted in whole currency units — the price of each sale is rounded down before it's added.
{% endhint %}


# SuperiorSkyBlock2

When [SuperiorSkyblock2](https://bg-software.com/superiorskyblock/) is installed, the `ssb2_rate_island` trigger becomes available. Detection is automatic.

| Trigger            | Counts when the player... | Progress     |
| ------------------ | ------------------------- | ------------ |
| `ssb2_rate_island` | rates an island           | 1 per rating |

The `target` controls which ratings count:

* `any` — any rating counts.
* `RATE:<1-5>` — only that exact star rating counts.

```yaml
objectives:
  explorer_critic:
    name: "&#7CF6FF&lIsland Critic"
    description:
      - "&#C7D0D9Visit other islands and"
      - "&#C7D0D9leave a rating."
      - ""
      - "&#8A8F98Progress: &#FFFFFF{progress}&#8A8F98/&#FFFFFF{required}"
    trigger: ssb2_rate_island
    target: any
    required: 3
```

Only counting 5-star ratings:

```yaml
objectives:
  generous_visitor:
    name: "&#FFD86E&lGenerous Visitor"
    trigger: ssb2_rate_island
    target: "RATE:5"
    required: 1
```

{% hint style="info" %}
The trigger fires for the player **giving** the rating, not the island owner receiving it. It's a social quest — a daily "rate 3 islands" quest is a cheap way to push players to actually visit each other's builds.
{% endhint %}


# Developer API

The plugin exposes a small API for other plugins: you can add your own objective triggers, reward types, register quests from code, listen to leveling events and modify per-player limits. This page assumes you're comfortable writing a Bukkit plugin.

### Setup <a href="#setup" id="setup"></a>

<div align="left"><figure><img src="https://img.shields.io/badge/dynamic/xml?url=https%3A%2F%2Frepo.mongenscave.com%2Freleases%2Fcom%2Fmongenscave%2Fmc-QuestAPII%2Fmaven-metadata.xml&#x26;query=%2Fmetadata%2Fversioning%2Flatest&#x26;style=for-the-badge&#x26;logoColor=%23F7556B&#x26;label=mc-QuestAPI" alt=""><figcaption></figcaption></figure></div>

{% tabs %}
{% tab title="Maven" %}

```xml
<repository>
  <id>MonGens-Cave</id>
  <url>https://repo.mongenscave.com/releases<repository></url>
</repository>

<dependency>
  <groupId>com.mongenscave</groupId>
  <artifactId>mc-QuestAPI</artifactId>
  <version>[VERSION]</version>
</dependency>
```

{% endtab %}

{% tab title="Gradle" %}

```groovy
maven { url "https://repo.mongenscave.com/releases" }

implementation "com.mongenscave:mc-QuestAPI:[VERSION]"
```

{% endtab %}
{% endtabs %}

And depend on the plugin in your `plugin.yml` so it loads first:

```yaml
depend: [mc-Quests]
```

The entry point is a static accessor, available from `onLoad()` onward:

```java
QuestAPI api = McQuests.getApi();
```

### The API at a glance <a href="#the-api-at-a-glance" id="the-api-at-a-glance"></a>

```java
public interface IQuestAPI {
    void registerObjective(ObjectiveHandler handler);
    void registerCondition(ConditionHandler handler);
    void registerReward(RewardHandler handler);
    void registerQuest(QuestDefinition quest);
    void giveQuest(Player player, String questId);
    void trigger(Player player, ObjectiveTrigger trigger, Object context);
}
```

### Custom objective triggers <a href="#custom-objective-triggers" id="custom-objective-triggers"></a>

This is the most useful extension point: it lets quest creators use *your* plugin's actions in `quests.yml`, just like the built-in triggers.

A trigger has two halves — an `ObjectiveHandler` that knows how to match and count an action, and a call to `api.trigger(...)` that fires when the action happens.

#### 1. Implement the handler <a href="#id-1-implement-the-handler" id="id-1-implement-the-handler"></a>

```java
public final class VoteObjective implements ObjectiveHandler {

    public static final ObjectiveTrigger VOTE = new ObjectiveTrigger("vote");

    @Override
    public ObjectiveTrigger trigger() {
        return VOTE;
    }

    @Override
    public boolean matches(String target, Object context) {
        if (!(context instanceof VoteContext vote)) return false;
        if (target == null || target.equalsIgnoreCase("any")) return true;

        return vote.serviceName().equalsIgnoreCase(target);
    }

    @Override
    public int progress(Object context) {
        return 1;
    }

    public record VoteContext(String serviceName) {}
}
```

* **`trigger()`** — the trigger's ID. It's what quest creators write in the `trigger:` field (IDs are lowercased automatically).
* **`matches(target, context)`** — decides whether this event counts for an objective with the given `target`. The `context` is whatever object you pass to `api.trigger(...)`; a small record is the usual pattern.
* **`progress(context)`** — how much progress the event is worth. Return `1` for count-based objectives, or an amount (damage, money, items) for total-based ones.

#### 2. Register it and fire it <a href="#id-2-register-it-and-fire-it" id="id-2-register-it-and-fire-it"></a>

```java
@Override
public void onEnable() {
    McQuests.getApi().registerObjective(new VoteObjective());
}

@EventHandler
public void onVote(VotifierEvent event) {
    Player player = Bukkit.getPlayerExact(event.getVote().getUsername());
    if (player == null) return;

    McQuests.getApi().trigger(player, VoteObjective.VOTE,
            new VoteObjective.VoteContext(event.getVote().getServiceName()));
}
```

#### 3. Use it in quests.yml <a href="#id-3-use-it-in-questsyml" id="id-3-use-it-in-questsyml"></a>

```yaml
objectives:
  voter:
    name: "&#B8FFF2&lSupporter"
    trigger: vote
    target: any
    required: 3
```

#### How a trigger call flows <a href="#how-a-trigger-call-flows" id="how-a-trigger-call-flows"></a>

`api.trigger(player, trigger, context)` only affects the given player, and only their **active** quests. For each active quest, every objective whose `trigger:` matches the trigger ID is tested with `matches(...)`; on a match, `progress(...)` is added (capped at `required`). Progress messages, objective/quest completion and rewards are all handled for you.

### Custom rewards <a href="#custom-rewards" id="custom-rewards"></a>

A `RewardHandler` adds a new `type:` for the `rewards:` section:

```java
public final class LootboxReward implements RewardHandler {

    @Override
    public String type() {
        return "lootbox";
    }

    @Override
    public void give(Player player, String value) {
        MyLootboxPlugin.give(player, value);
    }
}
```

```java
McQuests.getApi().registerReward(new LootboxReward());
```

```yaml
rewards:
  - type: lootbox
    display-name: "&#FFD86E1x Rare Lootbox"
    value: rare
```

The `value` arrives as the raw string from the config — parsing (amounts, `:` separators) is up to you.

### Custom conditions <a href="#custom-conditions" id="custom-conditions"></a>

The `ConditionHandler` interface mirrors rewards — `type()` plus a `check(player, value)` that returns whether the player may accept the quest:

```java
public final class TownyCondition implements ConditionHandler {

    @Override
    public String type() {
        return "town";
    }

    @Override
    public boolean check(Player player, String value) {
        return TownyAPI.getInstance().getTown(value).hasResident(player.getName());
    }
}
```

{% hint style="warning" %}
Condition registration is currently a stub: quest-accept checks only evaluate the built-in `permission` and `world` conditions, so handlers registered through `registerCondition(...)` are not consulted yet. Register them for forward compatibility, but don't rely on them gating quests today.
{% endhint %}

### Registering quests from code <a href="#registering-quests-from-code" id="registering-quests-from-code"></a>

`registerQuest(...)` adds a quest built with `QuestDefinition.builder()` — the same model the YAML loader produces:

```java
QuestDefinition quest = QuestDefinition.builder()
        .id("event_boss_hunt")
        .level(10)
        .daily(false)
        .objectives(List.of(
                ObjectiveDefinition.builder()
                        .id("kill_boss")
                        .trigger("kill_mythic_mob")
                        .target("EventBoss")
                        .requiredAmount(1)
                        .name("&#FF6B6BSlay the Event Boss")
                        .description(List.of("&7Defeat the boss before it escapes."))
                        .build()))
        .conditions(List.of())
        .rewards(List.of(
                RewardDefinition.builder()
                        .type("quest_xp")
                        .value("500")
                        .build()))
        .acceptExpire(-1)
        .activeExpire(30 * 60 * 1000L)
        .build();

McQuests.getApi().registerQuest(quest);
```

Note that `acceptExpire`/`activeExpire` are **milliseconds** here (`-1` = no limit), unlike the seconds used in `quests.yml`.

{% hint style="warning" %}
`/quests reload` rebuilds the quest list from `quests.yml`, which wipes code-registered quests. If your quests must survive reloads, re-register them — or ship them as YAML and only use the API for the trigger/reward logic.
{% endhint %}

To hand a quest to a player programmatically:

```java
McQuests.getApi().giveQuest(player, "event_boss_hunt");
```

This goes through the same pipeline as clicking the quest board — limits and conditions are checked, so it can fail silently. For unconditional grants, mirror the `/quests force give` admin command instead.

### Events <a href="#events" id="events"></a>

Two Bukkit events cover the leveling system:

#### `PlayerXpGainEvent` <a href="#playerxpgainevent" id="playerxpgainevent"></a>

Fires before quest XP is applied. Cancellable, and the amount is mutable — this is the hook for custom XP boosters:

```java
@EventHandler
public void onXpGain(PlayerXpGainEvent event) {
    if (event.getPlayer().hasPermission("myserver.booster")) {
        event.setAmount(event.getAmount() * 2);
    }
}
```

Getters: `getPlayer()`, `getAmount()` / `setAmount(double)`, `getOriginalAmount()`, `getLevel()`, `getCurrentXp()`.

#### `PlayerLevelUpEvent` <a href="#playerlevelupevent" id="playerlevelupevent"></a>

Fires once per level gained (a big XP grant can fire it several times in a row). Not cancellable — it's a notification:

```java
@EventHandler
public void onLevelUp(PlayerLevelUpEvent event) {
    broadcastMilestone(event.getPlayer(), event.getNewLevel());
}
```

Getters: `getPlayer()`, `getOldLevel()`, `getNewLevel()`.

### Per-player stat modifiers <a href="#per-player-stat-modifiers" id="per-player-stat-modifiers"></a>

A `QuestUserModifier` lets you adjust a player's computed limits and multipliers — the same numbers the level bonuses and premium pass feed into:

```java
McQuests.getInstance().getModifiers().add((player, user) -> {
    if (player.hasPermission("myserver.mvp")) {
        user.setDailyBoardSize(user.getDailyBoardSize() + 1);
        user.setXpMultiplier(user.getXpMultiplier() * 1.1);
    }
});
```

The `MutableQuestUser` exposes `maxAccepted`, `maxActive`, `dailyBoardSize`, `xpMultiplier` and `rewardMultiplier`. Modifiers run after the base + per-level values are computed; premium bonuses are applied on top of the result.

{% hint style="info" %}
The computed user object is cached. If your modifier's inputs change at runtime (a rank purchase, a toggled booster), call `McQuests.getInstance().getQuestUserService().invalidate(player)` to force a rebuild.
{% endhint %}

### Built-in trigger constants <a href="#built-in-trigger-constants" id="built-in-trigger-constants"></a>

All built-in trigger IDs are available as constants in `com.mongenscave.mcquests.api.trigger.Triggers` (`Triggers.BLOCK_BREAK`, `Triggers.KILL_MYTHIC_MOB`, ...). Use them instead of constructing `ObjectiveTrigger` by hand when firing or comparing built-in triggers — see [How to Create a Quest](/premium-products/quests/features/create-a-quest) for the full list and their semantics.


# mc-FunGun

Inject a new vibe into your Lobby servers and create a cheerful atmosphere!

<figure><img src="/files/vFoDI4NIlDaehC1Zlqwh" alt=""><figcaption></figcaption></figure>

### Plugin Features

* Multiple server support
* MySQL, H2 and SQLite Database support
* Up-to-date plugin
* 30+ pre-made FunGun effect
* 5 pre-made FunGun ability
* Optimized plugin, does not cause lag
* Fully customizable config, guis, messages and effects
* Editable messages, pre-made English and Hungarian language
* Hex color code Support
* Can make your own FunGun effect
* Folia Support
* Custom Model Data support

{% hint style="info" %}
Whatever complex request you have for the plugin, we will solve it for you!
{% endhint %}


# Plugin FAQ

Here are the features of the plugin, along with answers to frequently asked questions

### What is this plugin? What does it do and why is it good?

* **The Answer Is:** This plugin brings an innovative system to the Lobby servers. Forget the old, outdated cosmetic plugins and create a new atmosphere that no one has ever experienced before.

### How does the plugin support multi servers?

* **The Answer Is:** If you are using MySQL, you can save your player-selected effects, abilities and server restarts, and if you have more than 1 Lobby server, you will have more flexibility and the saved settings will be preserved!

```yaml
storage:
  #  driver: h2 / sqlite / mysql
  driver: 'mysql' # Use MySQL
  host: 'database-host'
  port: '3306'
  name: 'database-name'
  username: 'database-username'
  password: 'database-password'

  pool: # HikariCP config (Do not edit if you do not know what it is)
    maximumPoolSize: 10
    minimumIdle: 5
    connectionTimeout: 30000
    maxLifetime: 1800000
    idleTimeout: 600000
```




---

[Next Page](/llms-full.txt/1)

