Skip to content

Battlecore

Shared library for the Snowbird battle mods. It owns arenas, rulesets, NPC trainers, rewards, cooldowns and the battle database, so Showdown and Battle Tower do not each build their own.

What it does

Battlecore has almost nothing player-facing. It gives the battle mods one shared set of tools:

  • Arenas: a list of battle arenas, saved in the database, that Showdown and Battle Tower claim and release.
  • Rulesets: the battle formats (level cap, team size, bans, clauses, Mega, Z-Moves, Dynamax). Showdown queues, tournaments and Battle Tower all read the same rulesets.
  • Battle plumbing: starts battles, spawns NPC trainers, saves a player's position and inventory state before a battle and puts it back after.
  • Rewards: pays items, money, PokeDollars, XP or commands, and tells the player in chat what they got (for example You received $500.). Command rewards stay silent on purpose.
  • Cooldowns: "N attempts per hour, day, week" limits for any battle feature.
  • Pokemon display: one shared way to draw a Pokemon's item lore (species, level, IVs, EVs, moves) so every battle menu looks the same.
  • Database: one shared MariaDB connection pool for all the battle mods.

The mods that need it: Showdown (compbattles, mod id showdown) and Battle Tower. Both fail to load without Battlecore. Runs on the server only. Clients install nothing.

How players use it

Players do not use Battlecore directly. They see it through Showdown and Battle Tower: the arena they get sent to, the format rules, and the reward messages.

Staff guide

All commands need op level 2. Most staff work happens in the Showdown and Battle Tower menus, which open the same Battlecore screens.

Manage arenas

/battlecore arena opens the Arena Manager: every arena in one list, plus a create button. /battlecore arena edit <id> opens one arena. From the GUI you can set the display name, turn the arena on or off, set Pos1 and Pos2, the warp point, the menu icon, the world, and where it can be used.

"Where it can be used" is a set of tags:

Tag Meaning
pvp Showdown ranked queue, tournaments and Draft Factory can pick it at random
tower Battle Tower can use it when a stage has no fixed arena
warp It shows in the player warp menu

A new arena starts disabled, with Pos1 and Pos2 both at your position. Set both corners and the teleport, then enable it. Showdown's /sd arena and the Battle Tower stage editor open this same manager.

The same things work from chat:

/battlecore arena list
/battlecore arena setpos1 forest
/battlecore arena setpos2 forest
/battlecore arena setteleport forest
/battlecore arena finalize forest Forest Clearing
/battlecore arena seticon forest minecraft:oak_sapling
/battlecore arena tp forest 1
/battlecore arena delete forest

Manage rulesets

Create and edit rulesets in the Showdown ruleset GUI (/sd ruleset). There is no separate Battlecore ruleset GUI. From chat:

/battlecore ruleset list
/battlecore ruleset list tower
/battlecore ruleset setscope gen9ou tournament
/battlecore ruleset reload

A ruleset's scope decides who sees it:

Scope In /queue join In tournament picker Battle Tower by id
ranked (default) yes yes yes
tournament no yes yes
tower no no yes

Reload

/battlecore reload re-reads rulesets and arenas in the background. It does not reload the database settings in battlecore-server.toml. Those need a restart.

Configuration

File What it is for How it goes live
config/battlecore-server.toml Database login and this server's name Restart
config/battlecore/rulesets/<id>.json One file per ruleset /battlecore reload or /sd ruleset reload
config/battlecore/lore/<layout>.json Which lines a Pokemon's item lore shows Restart
  • server.name must match the server's Velocity key (main, hub, events, build, staging). Arenas are saved per server, so a wrong name shows another server's arenas.
  • The live server config is in config/, not world/serverconfig/, on this network.
  • A ruleset needs both a database row and a JSON file. A JSON file with no row is ignored. A row with no file gets a file of defaults written for it. Create rulesets in the GUI, not by dropping in a file.
  • Ruleset mechanic switches (allowMega, allowUltraBurst, allowZMoves, allowDynamax, allowGigantamax) are on by default. They can only be changed with /showdown ruleset set <id> <field> <true|false> or in the JSON file. The GUI does not show them.

Data and storage

MariaDB, in the database named in battlecore-server.toml. Battlecore creates these tables on start and owns them:

Table Holds
players UUID and name of everyone who used a battle feature
rulesets Ruleset id, name, description, enabled, scope
arenas Arenas, keyed by server name and arena id
seasons Ranked seasons
bc_attempts Cooldown history: player, feature, instance, time

Showdown and Battle Tower keep their own tables in the same database. Do not delete arenas or rulesets rows by hand while a server is running. Use the GUI.

Troubleshooting

Symptom Cause Fix
Showdown or Battle Tower does not load Battlecore missing or failed to load Check that battlecore-*.jar is in mods/ and look for errors from battlecore in latest.log
Queues, arenas or rewards do nothing, no errors in chat Database unreachable Battlecore keeps running and reconnects by itself when MariaDB comes back. Check the database and the login in battlecore-server.toml
A new ruleset file never shows up No database row for it Create the ruleset in /sd ruleset
Arena list shows the wrong arenas server.name does not match this server Fix it in battlecore-server.toml and restart
A Mega or Dynamax is blocked mid-battle The ruleset turns that mechanic off Expected. Check /showdown ruleset info <id>
A player won a money reward but got nothing The economy refused the deposit Look for a reward warning in latest.log. The player is not told about a failed payout

Boot lines that show it loaded correctly:

Battlecore database connected.
Battlecore database schema verified.
Battlecore commands registered.

Maintainer notes

  • Mechanic rules are uneven because Pixelmon is. Pixelmon has no per-battle rule for Mega, Ultra Burst, Dynamax or Gigantamax. BattleMechanicGuard cancels their battle events when a ruleset forbids them. Z-Moves have no such event, so a Z-Crystal holder is rejected at team validation instead. Battles with no policy (Battle Tower, raids, wild) allow everything.
  • BattleRuleApplier is the one place a ruleset becomes Pixelmon battle rules. Ranked and tournament code used to each have a copy, and they drifted.
  • Database threading. No JDBC on the server thread. Use DbExecutor.runAsync or supplyAsync (one worker thread, FIFO, futures never fail: failures are logged and the caller's fallback is used). Come back with DbExecutor.onServerThread before touching players. Database.isAvailable() is false while the ConnectionGuard breaker is tripped, so callers skip work instead of blocking. Hikari uses initializationFailTimeout=0, so the pool starts even when MariaDB is down, and the guard re-runs migrations when it comes back. On stop the executor drains, and Database.init re-arms it on the next start.
  • Pokemon lore. Fields are looked up by string id from the layout JSON, never by a Java call, so adding a field never forces a rebuild of GTS, Battle Tower or Showdown. Keep PokemonLoreService.render(Pokemon, String) unchanged; add overloads instead.
  • Rewards. The chat notice reports what was actually paid, not what was configured. RewardDisplay has no Minecraft imports so unit tests can load it.
  • Using Battlecore from a new feature: depend on battlecore with ordering = "AFTER", implement BattleListener and register it with BattleEventBus on server start, claim an arena with ArenaService, capture state with SavedPlayerState, start the battle with BattleStarter, and on battle end pay with RewardService and restore state. Battle Tower is the worked example.
  • Unit tests run without Minecraft, Pixelmon or a database. They reset static state with the *ForTesting() hooks.

Building

./gradlew build

Output: build/libs/battlecore-<version>.jar. Also runs the JUnit tests and a JaCoCo report. Watch out: build is followed by a deploy task that copies the new jar over every battlecore-*.jar it finds in a mods/ folder in this repo.

Full command, permission and config tables: Reference.