Skip to content

Development

This guide is for contributors, maintainers, and plugin authors who need to understand how OpenEco is built internally.

For the public addon-facing contract, read Addon API. Server owners should use the Production guide and Configuration instead.

Project layout

PathPurpose
src/main/java/.../OpenEcoPlugin.javaBootstrap, service registration, schedulers, reload, shutdown
api/src/main/java/.../OpenEcoApi.javaPublic immutable API (JitPack-published)
src/main/java/.../service/Core business logic, registry, cache, history
src/main/java/.../storage/JDBC repository and dialect-specific schema
src/main/java/.../economy/VaultUnlocked v2 and legacy Vault v1 adapters
src/main/java/.../command/Bukkit command handlers
src/main/java/.../event/Bukkit events
src/main/java/.../listener/Player join/quit sync logic
src/main/java/.../placeholder/PlaceholderAPI expansion
enhancements-addon/Interest, pay limits, perm caps, exchange
migrator-addon/Economy plugin import
proxy-addon/Velocity proxy handoff helper

Startup lifecycle

OpenEcoPlugin.onEnable():

  1. Save default config.
  2. Resolve storage backend and open JdbcAccountRepository.
  3. Create AccountService and initialize account loading strategy.
  4. Load message templates.
  5. Register OpenEcoApi in Bukkit's ServicesManager.
  6. Register VaultUnlocked v2 and legacy Vault v1 providers.
  7. Register commands, listeners, and optional PlaceholderAPI expansion.
  8. Start autosave and history prune schedulers.

If storage open or initial account load fails, the plugin disables itself.

reloadSettings() reloads config and messages, then restarts autosave and prune schedules.

onDisable() cancels schedulers, unregisters services, drains history, flushes dirty state, and closes JDBC.

Runtime model

OpenEco is an in-memory economy with single-JVM authority and JDBC persistence.

  • Live state in AccountRegistry.
  • Normal reads/writes do not round-trip to the database.
  • Dirty rows flush on autosave interval and clean shutdown.
  • History writes through a dedicated single-thread executor.
  • Baltop cached with TTL as immutable snapshots.

Main components

AccountService

Orchestration layer: account lifecycle, history reads, leaderboard reads, config snapshots.

EconomyOperations

Balance and pay rules: amount validation, max balance, tax, cooldown, event dispatch, history creation.

TransactionHistoryService

Serializes history inserts on a daemon executor. New mutations should use this service, not a separate executor.

JdbcAccountRepository

Only built-in persistence. Supports SQLite, H2, MySQL, MariaDB, PostgreSQL. Account deletes also delete that account's transaction rows.

Threading rules

  • Call mutating logic from a safe server context.
  • Paper: normal server thread.
  • Folia: owning region thread for the player or entity involved.
  • Autosave and history prune run on Paper's async scheduler.
  • Player-targeted replies on Folia must return through the player's scheduler.

Integration surfaces

SurfaceUse when
OpenEcoApiSame-server plugin integration (preferred)
Vault v1 / VaultUnlocked v2Compatibility with existing economy plugins
Bukkit eventsObserve or veto lifecycle and balance changes

Main events: AccountCreateEvent, AccountRenameEvent, AccountDeleteEvent, BalanceChangeEvent, BalanceChangedEvent, PayEvent, PayCompletedEvent.

Pre-mutation events (AccountRenameEvent, AccountDeleteEvent, BalanceChangeEvent, PayEvent) are cancellable.

Build and test

bash
./gradlew build
./gradlew test
./gradlew shadowJar

Notes:

  • Runtime libraries load through the libraries: section in plugin.yml.
  • The build patches VaultUnlocked module metadata back to Java 21.
  • stress-addon/ is included only when the directory exists.

Safe change checklist

If you change...Also verify...
Amount validation or balance rulesEconomyOperations, API statuses, Vault adapters, tests
Name/account lifecycleAccountService, PlayerConnectionListener, API docs
History writingTransactionHistoryService, history command, API docs
Baltop logicCache invalidation, snapshot immutability, rank lookups
Storage schemaSQLite and H2 behavior, integration tests
Scheduler usagePaper vs Folia safety, reply dispatch

Entry points

TaskStart here
Money logicservice/EconomyOperations.java
Account lifecycleservice/AccountService.java
Persistencestorage/JdbcAccountRepository.java
Plugin bootOpenEcoPlugin.java
Addon contractapi/OpenEcoApi.java
Vault adapterseconomy/OpenEcoEconomyProvider.java