Skip to content

Economy

Petrus Pradella edited this page Jul 28, 2026 · 1 revision

Economy

One entry point on every platform: FCEcoUtil, in br.com.finalcraft.evernifecore.util. It works the same on Bukkit and Hytale, and your plugin never imports Vault.

import br.com.finalcraft.evernifecore.util.FCEcoUtil;

// The 90% case: charge, and let the player know when the balance is short
if (!FCEcoUtil.ecoTake(player, 500).warnIfInsufficient(player)) {
    return;
}

double balance          = FCEcoUtil.ecoGet(uuid);
BigDecimal balanceExact = FCEcoUtil.ecoGetInBigDecimal(uuid);
FCEcoUtil.ecoGive(uuid, 250);

EcoResponse response = FCEcoUtil.ecoSet(uuid, 1000);
if (!response.isSuccess()) {
    getLogger().warning("eco set failed: " + response);
}

String pretty = FCEcoUtil.ecoFormat(1234.5); // rendered by the economy plugin itself

Every verb takes an IPlayerData, a UUID or an FPlayer, in double and BigDecimal forms. The double overloads convert once, here; everything below compares with compareTo only.

EcoResponse

Mutations (ecoGive, ecoTake, ecoSet) answer with an EcoResponse, because a boolean cannot tell "the balance was already the target" from "the provider refused":

Member What it gives you
isSuccess() whether money ended where you asked
getReason() SUCCESS, INSUFFICIENT_FUNDS, INVALID_AMOUNT, PROVIDER_ERROR
getAmount() the amount the call asked for
getBalance() the balance after the call, or the current one when it failed (never null)
getDetail() the provider's own error text, on PROVIDER_ERROR
warnIfInsufficient(FPlayer) sends the localized "not enough money" message when funds were short, and returns isSuccess()

warnIfInsufficient uses the balance the response already carries, so there is no second read and no window between checking and charging.

The semantics every implementation owes

These hold on Vault v1, on VaultUnlocked and on Hytale - the differences between them used to leak into plugins:

Call Result
negative amount INVALID_AMOUNT; the economy plugin is never called
ecoGive / ecoTake of zero success, nothing moves
ecoSet to the balance the account already has success - reaching the target is not a failure
ecoTake without funds INSUFFICIENT_FUNDS; the balance never goes negative
ecoHasEnough of zero or less true
transaction the provider refuses PROVIDER_ERROR carrying its text - never a silent success
ecoGet on an account the economy does not know zero, never null

Calls are synchronous: make them from the main thread. Thread-safety is whatever the economy plugin offers.

A server without economy

Every FCEcoUtil call throws IllegalStateException with an actionable message - reads included. A shop that silently charges nothing is worse than one that fails loudly.

To degrade on purpose, gate on availability:

if (FCEcoUtil.isEcoAvailable()) {
    registerShopCommands();
}

The console tells the two failure modes apart, because the fix differs:

  • "Vault plugin was not found" - install Vault/VaultUnlocked.
  • "Vault is present but no Economy plugin registered an economy service" - Vault is there and nothing is behind it (with a hint about CMI's economy module and FinalEconomy).
  • "No economy provider registered - this is an EverNifeCore platform wiring bug" - not your server's fault: the platform module failed to register anything at all.

The diagnostic runs once, on the first tick, when every plugin has enabled - an economy that registers after EverNifeCore is normal and produces no warning at all.

Multi-currency, banks and provider extras

Out of scope on purpose: the contract is single-currency. When you need more, take the wheel:

IEconomyProvider provider = EverNifeCore.getProviders().getEconomy();
net.milkbowl.vault2.economy.Economy vault2 = (net.milkbowl.vault2.economy.Economy) provider.getHandle();

getHandle() is the escape hatch to the underlying economy object. What you do with it is tied to that specific economy API, so guard it accordingly.

Implementing a provider

An economy plugin can register itself instead of going through Vault:

EverNifeCore.getProviders().getBaseProvider().register(IEconomyProvider.class, myProvider);

IEconomyProvider is BigDecimal-only and UUID-keyed. Verify an implementation with EconomyConformance from evernifecore-common-tests: check(provider) is read-only, and checkMutating(provider, scratchAccount) exercises the money-moving rules on an account you name.

Registering a provider replaces whatever the platform found, so do it when your economy should be the one EverNifeCore uses.

Clone this wiki locally