promotional bannermobile promotional banner
premium banner
A server-wide economy backbone (SQLite).

Description

CannaTaleEconomy

CannaTaleEconomy is the economy backbone for the CannaTale Hytale server ecosystem. It provides a persistent SQLite-backed balance system, player and admin commands, a configurable paycheck system (including a VIP tier), and a public API that other mods can call.


Features

Core

  • Persistent balances stored in SQLite (economy.db)
  • Whole-number currency (Long) to avoid floating point rounding issues
  • Atomic transfers using database transactions
  • Leaderboard queries for /baltop

Commands

  • Player: /balance, /baltop, /pay, /paycheck
  • Admin: /money set|give|take (single permission node)

Paycheck System (VIP Override)

  • Configurable interval and amounts
  • VIP permission node: cannatale.economy.vip
  • VIP players receive only paycheckAmountVip when using /paycheck (normal paycheckAmount is ignored)

Public API Hooks

  • Other mods can call EconomyApi to read/modify balances, transfers, leaderboards, formatting, and paycheck claims
  • Intended to be called from the server thread (same as commands/events)

Installation

  1. Build the plugin jar (see Build section).
  2. Copy the non-plain jar from build/libs/ into your server mods folder (example: HytaleServer/mods/).
  3. Start the server.
  4. On first run, Economy will generate its data files in the plugin data directory:
    • config.json
    • economy.db

Configuration (config.json)

Economy creates config.json on first run.

Current config keys:

  • startingBalance (Long)
    Starting balance for brand-new players.

  • paycheckAmount (Long)
    Default paycheck amount (non-VIP).

  • paycheckAmountVip (Long)
    VIP paycheck amount. Only used if player has cannatale.economy.vip.

  • paycheckIntervalMinutes (Long)
    Shared paycheck cooldown (minutes) for both tiers.

  • balTopLimit (Int)
    Number of entries shown in /baltop.

  • schemaVersion (Int)
    Internal version used for future migrations.

VIP behavior

If a player has cannatale.economy.vip, /paycheck pays only paycheckAmountVip and ignores paycheckAmount.


Permissions

Admin (all /money commands)

  • cannatale.economy.admin

VIP paycheck tier

  • cannatale.economy.vip

Commands

Root help

  • /economy
  • /ec (alias)

Shows the formatted command list.


Player commands

/balance

Shows your balance.

/balance [player]

Shows another player's balance.

Examples:

  • /balance
  • /balance Xion28080

/baltop

Shows the top balances (default top 10, configurable via balTopLimit).

Example:

  • /baltop

/pay <player> <amount>

Pays another player.

  • Amount must be > 0
  • Sender must have enough balance
  • Transfer is atomic

Example:

  • /pay Bob 250

/paycheck

Claims your paycheck.

  • Enforced by cooldown: paycheckIntervalMinutes
  • VIP players receive paycheckAmountVip only

Example:

  • /paycheck

If not ready, you will see a message showing the remaining time until the next claim.


Admin commands (require cannatale.economy.admin)

/money set <player> <amount>

Sets a player's balance.

/money give <player> <amount>

Adds to a player's balance.

/money take <player> <amount>

Removes from a player's balance (money is deleted, not transferred).

  • Clamped at 0 (no negative balances)

Examples:

  • /money set Bob 1000
  • /money give Bob 250
  • /money take Bob 500

Online-player note (ArgTypes.PLAYER_REF)

Several commands use ArgTypes.PLAYER_REF, which typically resolves to online players:

  • /pay
  • /money set|give|take
  • /balance --player=<name> (if the argument is resolved as PLAYER_REF)

If you want offline support (setting/checking players who are not online), Economy can be extended to resolve UUIDs via a profile store or name→UUID cache.


Database

SQLite file:

  • economy.db

Schema (conceptual):

  • Table balances
    • uuid (TEXT PRIMARY KEY)
    • name (TEXT)
    • balance (INTEGER)
    • last_paycheck_claim_ms (INTEGER)

Notes:

  • Amounts are stored as integers (Long)
  • Transfers use a transaction to avoid partial updates

Public API Hooks (Declared)

Where the API lives

Package:

  • org.omeganode.cannataleeconomy.api

Primary interface:

  • EconomyApi

Registry:

  • EconomyApiRegistry

How other mods obtain the API

import org.omeganode.cannataleeconomy.api.EconomyApiRegistry

val econ = EconomyApiRegistry.get() ?: return // Economy not loaded / not registered

EconomyApi — Methods and Hooks (exact)

All currency amounts are whole-number Long values.

Most methods accept nameForCreate so the account can be created on demand if missing.

package org.omeganode.cannataleeconomy.api

import org.omeganode.cannataleeconomy.data.EconomyConfig
import org.omeganode.cannataleeconomy.db.TopBalanceEntry
import org.omeganode.cannataleeconomy.services.PaycheckService
import java.util.UUID

interface EconomyApi {
    fun getConfig(): EconomyConfig

    fun ensure(uuid: UUID, nameForCreate: String)

    /** Returns starting balance if the account doesn't exist (does NOT create an account). */
    fun getBalance(uuid: UUID): Long

    /** Returns balance and creates account if needed. */
    fun getBalance(uuid: UUID, nameForCreate: String): Long

    fun setBalance(uuid: UUID, nameForCreate: String, amount: Long)

    fun give(uuid: UUID, nameForCreate: String, amount: Long)

    /**
     * Takes up to [amount] from the player's balance (clamped at 0).
     * @return the new balance after the take.
     */
    fun take(uuid: UUID, nameForCreate: String, amount: Long): Long

    /**
     * Transfers [amount] from one player to another.
     * @return true if success, false if sender lacks funds or amount <= 0.
     */
    fun transfer(fromUuid: UUID, fromName: String, toUuid: UUID, toName: String, amount: Long): Boolean

    fun top(limit: Int): List<TopBalanceEntry>

    /** Formats a number with commas using the server's locale rules used by Economy. */
    fun format(amount: Long): String

    /** Claim paycheck. If isVip=true, uses paycheckAmountVip only. */
    fun claimPaycheck(uuid: UUID, nameForCreate: String, isVip: Boolean): PaycheckService.ClaimResult
}

API Examples for other mods

Read balance (no account creation)

val bal = econ.getBalance(playerUuid)

Read balance (create account if missing)

val bal = econ.getBalance(playerUuid, playerName)

Give / take / set

econ.give(playerUuid, playerName, 500)
val newBal = econ.take(playerUuid, playerName, 250)
econ.setBalance(playerUuid, playerName, 1000)

Transfer

val ok = econ.transfer(fromUuid, fromName, toUuid, toName, 200)

Leaderboard

val top = econ.top(10)

Formatting

val formatted = econ.format(1234567) // "1,234,567"

Paycheck claim (VIP-aware)

val isVip = sender.hasPermission("cannatale.economy.vip")
val result = econ.claimPaycheck(playerUuid, playerName, isVip)

Troubleshooting

SQLite driver error at runtime

If you see: No suitable driver found for jdbc:sqlite:...

You likely deployed the wrong jar.

Fix:

  • Deploy the non-plain jar from build/libs/
  • Remove older Economy jars from the server mods folder
  • Restart the server