Skip to content

Building from Source

BeestoXd edited this page Aug 15, 2026 · 1 revision

Building from Source

Requirements

  • JDK 21+
  • Maven

Everything else is pulled from the repositories declared in pom.xml.

Build

git clone https://github.com/BeestoXd/UltimateVirtualSpawner.git
cd UltimateVirtualSpawner
mvn clean package

On Windows, build.bat runs the same thing.

The jar lands at target/UltimateVirtualSpawner-<version>.jar. Drop it into a test server's plugins/ folder.

Run just the tests:

mvn test

Project layout

src/main/java/com/bx/ultimateVirtualSpawner/
├── commands/    command executors and tab completion
├── compat/      server/version detection and the compatibility gate
├── economy/     balances, providers (internal / Vault), money arithmetic
├── hooks/       PlaceholderAPI and Vault integration
├── listeners/   Bukkit event handling
├── managers/    spawner, storage, config and database state
├── menus/       GUI construction and click handling
├── models/      plain data types
├── tasks/       scheduled work (spawn cycles, saving)
└── utils/       shared helpers

src/main/resources/   config.yml, spawners.yml, menus.yml, messages.yml, sounds.yml, plugin.yml
src/test/java/        JUnit 5 tests

The pieces that matter

Class Role
UltimateVirtualSpawner Plugin entry point. Boots the compatibility gate, then the managers, in order.
SpawnerManager The core. Owns every spawner in memory, the generation cycle, placing, stacking, breaking, selling.
DatabaseManager JDBC access on a dedicated daemon thread. Creates the schema, loads and saves.
ConfigManager Loads the five YAML files and back-fills missing keys from the packaged defaults.
EconomyManager Picks a provider (internal or Vault) and publishes the Vault bridge.
WorthManager Sell prices and permission multipliers.
AntiEspManager Per-player spawner concealment.
SpigotScheduler The Folia / Bukkit scheduler abstraction.
ServerCompatibility Version parsing and the start-up gate.

Version ranges

Supported ranges are Maven properties in pom.xml, filtered into src/main/resources/compatibility.properties and plugin.yml at build time:

<paper.supported.min>1.21.10</paper.supported.min>
<paper.supported.max>26.2</paper.supported.max>
<folia.supported.min>1.21.11</folia.supported.min>
<folia.supported.max>26.2</folia.supported.max>

Change them there, not in the Java — ServerCompatibility reads the generated properties file at runtime, falling back to its own constants only if the resource is missing.

JDBC drivers

SQLite and MySQL are declared as libraries in plugin.yml rather than shaded in, so the server downloads them on first start and the jar stays small. Bump their versions through the sqlite.version and mysql.version properties in pom.xml.

Testing changes

Unit tests only cover pure logic — version parsing and money maths. Bukkit is not mocked, so behaviour changes need a live server.

  • Test on Paper at minimum.
  • If your change touches world access, scheduling, or anything in tasks/ or listeners/, test on Folia too. The region scheduler behaves differently, and code that works on Paper can deadlock or throw there.

To start on an unsupported build for testing, set COMPATIBILITY.STRICT: false or COMPATIBILITY.ENABLED: false in config.yml.

Code style

Match the surrounding code rather than reformatting it.

  • 4-space indentation, braces on the same line, UTF-8, LF endings.
  • Classes not designed for extension are final; fields are private final where possible.
  • No wildcard imports.
  • Comments explain why, not what. Most methods need none.
  • All world, block and entity access goes through the region scheduler — never assume the main thread. This is the single most common source of Folia breakage.
  • No new hard dependencies. Vault and PlaceholderAPI are soft-depends, and the plugin must keep working without them.

Changing configuration files

Missing keys are back-filled from the packaged defaults on every load, so updating never wipes a server owner's values. To keep that true:

  • Add keys — never rename or remove one without a migration path.
  • Add the key to the packaged default in src/main/resources/, with a comment explaining it.
  • Text goes in messages.yml, GUI layout in menus.yml, sounds in sounds.yml. Never hardcode player-facing strings in Java.
  • If a new option only takes effect on restart, say so in its comment.

Tests

JUnit 5, in src/test/java/, mirroring the main package structure. Bukkit is not mocked, so tests target pure logic — see MinecraftVersionTest, ServerCompatibilityTest and MoneyMathTest for the pattern.

If a bug fix can be expressed as a failing test, add one. It is the clearest way to show the fix works.

See also

Clone this wiki locally