> For the complete documentation index, see [llms.txt](https://docs.craftingtable.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.craftingtable.org/plugin-documentation/cubeeco.md).

# CubeEco

A modular, **unlimited‑currency** economy plugin for modern Minecraft servers. Define as many currencies as you like in simple YAML files — each gets its own command, leaderboard, withdrawable notes, tax rules, and formatting. CubeEco bridges to Vault, PlaceholderAPI, ShopGUI+, EconomyShopGUI, and Towny out of the box.

* **Version:** 1.1.0
* **Server:** Paper 1.21+ (Folia supported)
* **Java:** 21+
* **Storage:** SQLite (default), MySQL, or flat‑file YAML

## Features

* **Unlimited currencies** — every `.yml` file in `currencies/` becomes a fully‑featured currency.
* **Per‑currency commands** — `/<currency> balance | pay | withdraw | top`, registered at runtime.
* **Physical notes** — withdraw a balance into a right‑click‑to‑redeem item.
* **Leaderboards** — chat **and** chest‑GUI top lists, refreshed on a schedule.
* **Tax** — optional percentage + flat fee on payments, routed to void / a bank account / broadcast.
* **GUIs** — balance overview, leaderboard, and withdraw‑denomination menus.
* **Deep integrations** — Vault, PlaceholderAPI, ShopGUI+ (multi‑currency), EconomyShopGUI, Towny.
* **MiniMessage everywhere** — gradients, hover, colour, all configurable.
* **Async, cached storage** — balances are cached in memory and flushed off the main thread.
* **Hot reload** — add or edit currencies and reload without a restart (a couple of caveats below).

## Requirements

| Component       | Requirement                                                               |
| --------------- | ------------------------------------------------------------------------- |
| Server software | Paper **1.21+** (Spigot may work; Paper recommended). Folia is supported. |
| Java            | **21** or newer                                                           |
| PlaceholderAPI  | Optional — enables `%cubeeco_…%` placeholders                             |
| Vault           | Optional — exposes CubeEco as a Vault economy provider                    |
| ShopGUIPlus     | Optional — multi‑currency shop support                                    |
| EconomyShopGUI  | Optional — single‑currency shop support (via Vault)                       |
| Towny           | Optional — town/nation economy + join reward                              |

All third‑party plugins are **soft‑depends**: if one isn't installed, CubeEco starts normally and silently skips that integration. SQLite and MySQL drivers are bundled inside the jar — nothing extra to install.

## Installation

{% stepper %}
{% step %}

## Get the jar

**Download** the latest `CubeEco-<version>.jar`, **or build it yourself:**

```bash
git clone https://github.com/bumpier/CubeEco.git
cd CubeEco
mvn package
```

The built plugin is written to `target/CubeEco-1.1.0.jar`. (Ignore `original-CubeEco-1.1.0.jar` — that's the un‑shaded copy without the bundled database drivers.)
{% endstep %}

{% step %}

## Install

1. Stop your server.
2. Drop `CubeEco-1.1.0.jar` into your server's `plugins/` folder.
3. Start the server. CubeEco generates its config and a default `emeralds` currency on first run.
4. (Optional) Install PlaceholderAPI / Vault / ShopGUI+ / EconomyShopGUI / Towny to enable those integrations, then restart.
   {% endstep %}

{% step %}

## File layout

After first run:

```
plugins/CubeEco/
├── config.yml            # main settings
├── messages.yml          # all player-facing text (MiniMessage)
├── database.db           # SQLite data (only when storage.backend: sqlite)
├── balances.yml          # flat-file data (only when storage.backend: yaml)
├── transactions.log      # human-readable log (only when logging.log-to-file: true)
└── currencies/
    └── emeralds.yml       # bundled example currency
```

{% endstep %}
{% endstepper %}

## Quick Start

{% stepper %}
{% step %}

## Start the server

Start the server once to generate the files above.
{% endstep %}

{% step %}

## Edit a currency

Open `currencies/emeralds.yml` and tweak the name, symbol, command, and caps to taste — or copy it to `currencies/coins.yml` to make a second currency.
{% endstep %}

{% step %}

## Reload

Run `/cubeeco admin reload` (or restart) to apply changes.
{% endstep %}

{% step %}

## Give yourself currency

Give yourself some currency: `/cubeeco admin give <you> emeralds 1000`.
{% endstep %}

{% step %}

## Test it

Check it: `/emerald balance` — and try `/emerald top`, `/emerald withdraw`, `/cubeeco`.
{% endstep %}
{% endstepper %}

## Configuration — `config.yml`

```yaml
storage:
  # Options: yaml, sqlite, mysql
  backend: sqlite

  mysql:
    host: localhost
    port: 3306
    database: cubeeco
    username: root
    password: ""
    pool-size: 10
    use-ssl: false

# The currency that backs the Vault economy provider.
# Must match a file name (without .yml) in /currencies/
vault-currency: "emeralds"

# If true, players sitting at 0 still appear on leaderboards.
leaderboard-show-zero: false

# How often leaderboard snapshots refresh, in seconds (min 30).
leaderboard-refresh-interval: 300

cache:
  # How often dirty balances are flushed to storage for online players (seconds).
  flush-interval: 60

# GUI sounds (vanilla enum names). Leave a value blank to silence it.
gui:
  open-sound: "UI_BUTTON_CLICK"
  success-sound: "ENTITY_PLAYER_LEVELUP"
  error-sound: "ENTITY_VILLAGER_NO"

logging:
  # Record every transaction to the ce_transactions table (SQL backends only).
  log-transactions: true
  # Also append a human-readable line to a file.
  log-to-file: false
  log-file: "transactions.log"

towny:
  enabled: true
  # Informational only — Towny actually charges the vault-currency through Vault.
  # Set vault-currency to this same currency for consistency.
  bank-currency: "emeralds"
  join-reward:
    enabled: false
    currency: "emeralds"
    amount: 100.0
```

| Key                            | Purpose                                                                    |
| ------------------------------ | -------------------------------------------------------------------------- |
| `storage.backend`              | `sqlite` (default), `mysql`, or `yaml`. **Changing this needs a restart.** |
| `storage.mysql.*`              | Connection details when `backend: mysql`.                                  |
| `vault-currency`               | Which currency Vault‑aware plugins (and EconomyShopGUI / Towny) use.       |
| `leaderboard-show-zero`        | Show players with a 0 balance on leaderboards.                             |
| `leaderboard-refresh-interval` | Seconds between leaderboard snapshot refreshes (minimum 30).               |
| `cache.flush-interval`         | Seconds between background flushes of changed balances to storage.         |
| `gui.*-sound`                  | Sounds for opening GUIs, successful actions, and errors.                   |
| `logging.log-transactions`     | Write each transaction to the `ce_transactions` table (SQL only).          |
| `logging.log-to-file`          | Also append a readable line to `logging.log-file`.                         |
| `towny.enabled`                | Master switch for the Towny join‑reward feature.                           |
| `towny.join-reward`            | Grant new town residents a currency reward (off by default).               |

## Creating Currencies

Every `.yml` file in `plugins/CubeEco/currencies/` is loaded as an independent currency. The **file name** (without `.yml`) is the currency's `id` — used for permissions and placeholders. To add a currency, copy `emeralds.yml`, rename it, edit it, and run `/cubeeco admin reload`.

Here is the bundled `emeralds.yml`, annotated:

```yaml
# Display name (MiniMessage) + singular/plural forms used in messages.
name: "<green>Emeralds"
name-singular: "Emerald"
name-plural: "Emeralds"

# Symbol shown in formatted balances, and where it sits (prefix | suffix).
symbol: "E"
symbol-position: prefix

# Primary command + aliases. Defaults to the file name if omitted.
command: "emerald"
command-aliases:
  - "em"

# Starting balance for brand-new players.
starting-balance: 0.0

# Caps. Set max-balance to -1 for unlimited. allow-negative permits debt.
max-balance: 1000000000.0
allow-negative: false

features:
  pay:
    enabled: true
    permission: "cubeeco.emeralds.pay"   # optional override of the default node
    min-amount: 1.0
    max-amount: 1000000.0
    cooldown: 0                            # seconds between payments (0 = none)
    allow-offline: false                   # allow paying offline players

  balance:
    enabled: true
    check-others: true
    permission-check-others: "cubeeco.emeralds.balance.others"

  withdraw:
    enabled: true
    permission: "cubeeco.emeralds.withdraw"
    item:
      material: EMERALD
      name: "<green><bold>Emerald Note"
      lore:
        - "<gray>Worth: <white><amount></white> Emeralds"
        - ""
        - "<yellow>Right-click to redeem!"
      custom-model-data: 0                 # for resource packs (0 = off)
      glowing: true
    # GUI buttons. "custom" lets the player type any amount in chat.
    denominations: [1, 10, 100, 1000, 10000, custom]

  top:
    enabled: true
    entries-per-page: 10

leaderboard:
  type: both            # chat | gui | both
  size: 100             # number of ranked players tracked
  chat:
    per-page: 10
  gui:
    title: "<gradient:#00c9ff:#92fe9d>Emerald Leaderboard</gradient>"
    rows: 6
    entry-slots: [10,11,12,13,14,15,16,19,20,21,22,23,24,25,28,29,30,31,32,33,34]
    entry-item:
      name: "<yellow>#<rank> <white><player>"
      lore:
        - "<gray>Balance: <white><balance>"
    filler:
      enabled: true
      material: BLACK_STAINED_GLASS_PANE
    prev-page-slot: 45
    next-page-slot: 53
    close-slot: 49

tax:
  enabled: false
  rate: 5.0             # percent of the payment
  destination: void     # void | bank | broadcast
  bank-player: ""        # player name/UUID that receives tax when destination: bank
  flat-fee: 0.0          # flat amount added on top of the percentage

formatting:
  style: compact         # full | compact | symbol-compact
  compact-decimals: 1
  thousands-separator: ","
  decimal-separator: "."
```

{% hint style="info" %}
Placeholders inside an item's `name`/`lore` such as `<amount>` are replaced when a note is created. Display text supports the full MiniMessage syntax (gradients, hover, etc.).
{% endhint %}

{% hint style="info" %}
If a currency file has a missing or invalid field, CubeEco logs a warning and falls back to a safe default rather than failing to load. A malformed currency never crashes the plugin.
{% endhint %}

## Number Formatting

Each currency's `formatting.style` controls how balances appear:

| Style            | Example (1,234,567) | Notes                                                                                 |
| ---------------- | ------------------- | ------------------------------------------------------------------------------------- |
| `full`           | `1,234,567`         | Grouped digits using your `thousands-separator` / `decimal-separator`.                |
| `compact`        | `1.2M`              | Suffixes K, M, B, T. `compact-decimals` sets decimal places; trailing zeros stripped. |
| `symbol-compact` | `E1.2M`             | Compact plus the currency `symbol` (prefix or suffix).                                |

Compact values round **down** (so a balance never displays as more than the player has). Regardless of the chosen style, PlaceholderAPI still exposes every format individually (see [PlaceholderAPI](#placeholderapi)).

## Commands

In the tables below, `<currency>` is a currency's configured command (e.g. `emerald` for `emeralds.yml`) plus any aliases, and `<id>` is its file name (e.g. `emeralds`).

### Per‑currency commands

| Command                              | Permission                                              | Description                                           |
| ------------------------------------ | ------------------------------------------------------- | ----------------------------------------------------- |
| `/<currency>`                        | `cubeeco.<id>.balance`                                  | Show your own balance (shorthand for `balance`)       |
| `/<currency> balance [player]`       | `cubeeco.<id>.balance` (+ `.balance.others` for others) | Show a balance                                        |
| `/<currency> pay <player> <amount>`  | `cubeeco.<id>.pay`                                      | Pay another player (tax applies if enabled)           |
| `/<currency> withdraw [amount\|gui]` | `cubeeco.<id>.withdraw`                                 | Withdraw a note; no amount opens the denomination GUI |
| `/<currency> top [page\|gui]`        | `cubeeco.<id>.top`                                      | Leaderboard, in chat or as a head GUI                 |

Aliases: `balance` → `bal`, `withdraw` → `wd`, `top` → `baltop`, `leaderboard`.

### Base command — `/cubeeco`

Aliases: `/currencies`, `/ceco`.

| Command                                            | Permission      | Description                                                    |
| -------------------------------------------------- | --------------- | -------------------------------------------------------------- |
| `/cubeeco`                                         | `cubeeco.use`   | Open the Balance Overview GUI (players); help text for console |
| `/cubeeco list`                                    | `cubeeco.use`   | List loaded currencies                                         |
| `/cubeeco help`                                    | `cubeeco.use`   | Show help                                                      |
| `/cubeeco admin give <player> <currency> <amount>` | `cubeeco.admin` | Add balance                                                    |
| `/cubeeco admin take <player> <currency> <amount>` | `cubeeco.admin` | Remove balance                                                 |
| `/cubeeco admin set <player> <currency> <amount>`  | `cubeeco.admin` | Set balance to an exact value                                  |
| `/cubeeco admin reset <player> <currency>`         | `cubeeco.admin` | Reset a player to the starting balance                         |
| `/cubeeco admin resetall <currency>`               | `cubeeco.admin` | Reset **every** player                                         |
| `/cubeeco admin bulkgive <currency> <amount>`      | `cubeeco.admin` | Give to all online players                                     |
| `/cubeeco admin reload`                            | `cubeeco.admin` | Reload config, messages, and currencies                        |
| `/cubeeco admin info <currency>`                   | `cubeeco.admin` | Print a currency's config summary                              |

Admin `give`/`take`/`set`/`reset` work on **offline** players too (they're loaded, updated, and saved in the background).

## Permissions

Replace `<id>` with a currency's file name (e.g. `emeralds`).

| Node                          | Default | Grants                                                    |
| ----------------------------- | ------- | --------------------------------------------------------- |
| `cubeeco.use`                 | `true`  | `/cubeeco` overview GUI, `/cubeeco list`, `/cubeeco help` |
| `cubeeco.admin`               | `op`    | Every `/cubeeco admin …` subcommand                       |
| `cubeeco.<id>.balance`        | `true`  | Check your own `<id>` balance                             |
| `cubeeco.<id>.balance.others` | `op`    | Check another player's `<id>` balance                     |
| `cubeeco.<id>.pay`            | `true`  | Send `<id>` payments                                      |
| `cubeeco.<id>.withdraw`       | `true`  | Withdraw `<id>` as physical notes                         |
| `cubeeco.<id>.top`            | `true`  | View the `<id>` leaderboard (chat + GUI)                  |

* `cubeeco.use` and `cubeeco.admin` are declared in `plugin.yml`. The per‑currency nodes are registered programmatically at startup and re‑registered on `/cubeeco admin reload`.
* **Overrides:** a currency file may set its own permission string for `pay`, `balance.others`, and `withdraw` (the `permission` / `permission-check-others` keys). When set, that custom node replaces the `cubeeco.<id>.*` default for that feature.

## Withdraw Notes

A withdraw note is a physical item carrying a fixed amount of a currency.

**Creating one:**

* `/<currency> withdraw <amount>` — instantly withdraws that amount as a note.
* `/<currency> withdraw` (or `/<currency> withdraw gui`) — opens the **denomination GUI** with one button per value in the currency's `denominations` list. A `custom` entry lets the player type any amount in chat.

The balance is deducted when the note is created, and the note's name/lore come from the currency's `withdraw.item` config (with `<amount>` substituted). Notes can carry custom model data for resource packs and can be made to glow.

**Redeeming one:** hold the note and **right‑click**. The amount is credited back and the item is consumed. If the currency was deleted in the meantime, the player is told the note is invalid.

## Leaderboards

* Each currency tracks the top `leaderboard.size` players.
* Snapshots refresh every `leaderboard-refresh-interval` seconds (`config.yml`) and on demand when a player runs `/<currency> top` and the data is stale.
* `leaderboard.type` chooses how `/<currency> top` renders by default:
  * `chat` — paginated chat list
  * `gui` — chest GUI of player heads
  * `both` — GUI for players, chat for console (players can force chat with a page number, or the GUI with `gui`).
* Players at 0 are hidden unless `leaderboard-show-zero: true`.

## GUIs

| GUI                        | Opened by                    | Behaviour                                                                                |
| -------------------------- | ---------------------------- | ---------------------------------------------------------------------------------------- |
| **Balance Overview**       | `/cubeeco`                   | One item per currency showing your balance. Click a currency to open its leaderboard.    |
| **Leaderboard**            | `/<currency> top` (GUI mode) | Player heads ranked by balance, with prev/next/close buttons. Fully styled per currency. |
| **Withdraw Denominations** | `/<currency> withdraw`       | One button per configured denomination; `custom` prompts for a chat amount.              |

Items can't be moved or dragged out of CubeEco GUIs. Open/success/error sounds are configurable in `config.yml`.

## Tax System

Tax applies **only to `/pay`** and is configured per currency under `tax`:

```yaml
tax:
  enabled: true
  rate: 5.0            # percent of the gross amount
  flat-fee: 0.0         # added on top
  destination: void     # void | bank | broadcast
  bank-player: ""        # required when destination: bank
```

* **Formula:** `tax = (amount × rate / 100) + flat-fee`.
* The **sender pays the full amount**; the **recipient receives `amount − tax`**.
* **Destinations:**
  * `void` — tax is removed from circulation.
  * `bank` — tax is credited to `bank-player`.
  * `broadcast` — tax is removed and a server‑wide message announces it.

The sender's confirmation shows both the amount sent and the tax deducted.

## PlaceholderAPI

Identifier: **`cubeeco`**. Install PlaceholderAPI to use these. `<id>` is the currency file name; `<n>` is a 1‑based leaderboard position.

| Placeholder                                | Output                                                      |
| ------------------------------------------ | ----------------------------------------------------------- |
| `%cubeeco_<id>_balance%`                   | Raw balance (e.g. `15230.5`)                                |
| `%cubeeco_<id>_balance_formatted%`         | Full, grouped (e.g. `15,230`)                               |
| `%cubeeco_<id>_balance_compact%`           | Compact (e.g. `15.2K`)                                      |
| `%cubeeco_<id>_balance_symbol%`            | Symbol + compact (e.g. `E15.2K`)                            |
| `%cubeeco_<id>_rank%`                      | Player's leaderboard rank (`-` if outside the cached top‑N) |
| `%cubeeco_<id>_top_<n>_name%`              | Name of player #n                                           |
| `%cubeeco_<id>_top_<n>_balance%`           | Raw balance of #n                                           |
| `%cubeeco_<id>_top_<n>_balance_formatted%` | Full balance of #n                                          |

{% hint style="info" %}
Balances read from the live cache, so **offline players resolve to `0`**. Rank and `top_<n>` placeholders read from the cached leaderboard snapshot.
{% endhint %}

## Integrations

All integrations are soft‑depends — missing plugins are skipped silently.

### Vault

CubeEco registers a Vault `Economy` provider (at `Highest` priority) backed by the currency named in `config.yml` → `vault-currency`. Any Vault‑aware plugin then reads and charges that single currency. This is the bridge that powers EconomyShopGUI and Towny.

### ShopGUI+ (multi‑currency)

ShopGUI+ is the one shop plugin where **every** CubeEco currency is usable independently. On ShopGUI+ post‑enable, CubeEco registers one custom economy provider per currency, named `cubeeco_<id>`.

```yaml
# In a ShopGUI+ shop file:
economy-type: CUSTOM
economy-type-custom: cubeeco_emeralds
```

{% hint style="warning" %}
**Reload caveat:** providers are registered once, at ShopGUI+ post‑enable, for the currencies loaded then. Adding a currency and running `/cubeeco admin reload` does **not** retroactively register it with ShopGUI+ — that needs a restart (or a ShopGUI+ reload that re‑fires its post‑enable event).
{% endhint %}

### EconomyShopGUI (via Vault)

EconomyShopGUI has no custom‑provider API. Point its economy provider at `Vault`; its shops then transact against CubeEco's `vault-currency` (single currency only).

### Towny (via Vault + join reward)

Towny's core economy (town/nation banks, plot claims, taxes) runs through Vault — leave Towny on its Vault economy and set CubeEco's `vault-currency` to the currency you want Towny to use. CubeEco adds an optional **join reward** on top:

```yaml
towny:
  enabled: true
  join-reward:
    enabled: true
    currency: "emeralds"
    amount: 100.0
```

## Storage Backends

| Backend              | When to use            | Notes                                                   |
| -------------------- | ---------------------- | ------------------------------------------------------- |
| `sqlite` *(default)* | Single server          | Stored in `database.db`. Driver bundled.                |
| `mysql`              | Networks / shared data | Configure `storage.mysql.*`. Driver + HikariCP bundled. |
| `yaml`               | Tiny servers / testing | Stored in `balances.yml`. **No transaction log.**       |

* Balances are cached in memory; reads/writes hit the cache and are flushed asynchronously every `cache.flush-interval` seconds and on quit.
* SQL backends use the tables `ce_balances` and (when `log-transactions: true`) `ce_transactions`.
* **Switching `storage.backend` requires a restart** (it is not hot‑reloadable) and does not migrate existing data between backends.

## Reloading

`/cubeeco admin reload`:

1. Re‑reads `config.yml` and `messages.yml`.
2. Rescans `currencies/` for new, changed, or removed files.
3. Unregisters commands/permissions for removed currencies and registers them for new ones.
4. Flushes dirty cache entries to storage.
5. Refreshes leaderboard snapshots.
6. Reports the currency count and elapsed time.

**Not** hot‑reloadable (require a restart):

* The **storage backend** (`storage.backend`).
* **ShopGUI+ economy providers** (registered once at ShopGUI+ post‑enable).

## Customising Messages

All player‑facing text lives in `messages.yml` and supports **MiniMessage** (colours, `<gradient>`, `<hover>`, etc.) plus PlaceholderAPI. Each message exposes context tokens like `<player>`, `<currency>`, `<amount>`, `<balance>`, `<tax>`, `<rank>`, and `<page>`. The `prefix` value is prepended to most messages.

```yaml
prefix: "<green><bold>CubeEco</bold></green> <dark_gray>»</dark_gray> "
balance-self: "<gray>Your <white><currency></white> balance is <white><balance></white>."
pay-sent: "<gray>You paid <white><player></white> <white><amount></white> <white><currency></white>. (Tax: <white><tax></white>)"
```

Edit the values, keep the `<tokens>` intact, and run `/cubeeco admin reload`.

## Troubleshooting

| Symptom                                              | Fix                                                                                                        |
| ---------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| Per‑currency command doesn't exist                   | Currency failed to load — check console for a warning, fix the `.yml`, then `/cubeeco admin reload`.       |
| New currency missing from ShopGUI+                   | ShopGUI+ providers register only at its post‑enable. **Restart** the server.                               |
| Balances not saving                                  | Confirm `storage.backend` and (for MySQL) the connection details; check console for DB errors.             |
| Placeholders show literally                          | Install PlaceholderAPI; confirm the `<id>` matches the currency file name.                                 |
| `%cubeeco_<id>_balance%` is `0` for an online player | The cache may still be loading right after join; it resolves momentarily. Offline players always read `0`. |
| Vault plugins use the wrong currency                 | Set `vault-currency` to the desired currency id and restart.                                               |
| Changed `storage.backend` did nothing                | Backend changes need a restart and do not migrate existing data.                                           |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.craftingtable.org/plugin-documentation/cubeeco.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
