BlockParty

BlockParty is a colored-floor elimination minigame for PaperMC servers. Players stand on a floor of colored blocks; each round a target color is announced and players must move onto it before time runs out. All other blocks vanish, anyone not standing on the target color (or standing on nothing) falls and is eliminated, and the floor is restored for the next, slightly faster round. Last player standing wins.

Requirements

  • PaperMC 1.21.x (API version 1.21)
  • Java 21
  • No other plugins required. Optional soft-dependencies: PlaceholderAPI, Vault.

Installation

  1. Download BlockParty-<version>.jar (see Building from source) or grab it from the CI build artifacts.
  2. Drop it into your server's plugins/ folder.
  3. Start/restart the server. config.yml, messages.yml and the arenas/ folder are created automatically under plugins/BlockParty/.

Commands

All admin/config commands live under /blockparty (alias /bp) and work from console where it makes sense (create, delete, enable, disable, info, list, reload). Commands that require a physical location (setlobby, setspawn, setspectator, pos1, pos2) require a player sender.

Admin

Command Description
/blockparty help Show command help
/blockparty create <arena> Create a new, disabled arena
/blockparty delete <arena> Delete an arena and its config file
/blockparty enable <arena> Validate and enable an arena
/blockparty disable <arena> Disable an arena, kicking anyone inside
/blockparty setlobby <arena> Set the waiting-room location
/blockparty setspawn <arena> Set the in-game spawn location
/blockparty setspectator <arena> Set the spectator/eliminated location
/blockparty pos1 <arena> Set floor region corner 1
/blockparty pos2 <arena> Set floor region corner 2
/blockparty setfloor <arena> <mat1,mat2,...> Set the allowed floor materials
/blockparty generate <arena> Randomly generate and persist the floor layout
/blockparty info <arena> Show arena configuration/status and validation errors
/blockparty list List all arenas
/blockparty reload Reload config.yml, messages.yml and arena definitions

Player

Command Description
/blockparty join <arena> Join an arena's waiting lobby
/blockparty leave Leave your current arena
/blockparty arenas List arenas (alias of list)
/blockparty stats [player] View your or another player's stats

Permissions

Permission Default Description
blockparty.play true Baseline permission to use player commands
blockparty.join true Allows joining arenas
blockparty.spectate true Allows spectating
blockparty.admin op Parent permission, grants all blockparty.admin.*
blockparty.admin.create op Create arenas
blockparty.admin.delete op Delete arenas
blockparty.admin.setup op Configure lobby/spawn/floor/etc, enable/disable
blockparty.admin.reload op Reload the plugin

Creating an arena — full walkthrough

  1. /bp create lobby1 — creates plugins/BlockParty/arenas/lobby1.yml.
  2. Stand where players should wait and run /bp setlobby lobby1.
  3. Stand where players should spawn on the floor and run /bp setspawn lobby1.
  4. Stand where eliminated players/spectators should go and run /bp setspectator lobby1.
  5. Stand at one corner of the floor area and run /bp pos1 lobby1.
  6. Stand at the opposite corner and run /bp pos2 lobby1.
  7. Either:
    • Run /bp setfloor lobby1 RED_CONCRETE,BLUE_CONCRETE,GREEN_CONCRETE,YELLOW_CONCRETE to choose the color palette (defaults to the full concrete rainbow if you skip this and just generate), then /bp generate lobby1 to lay out and persist a random floor, or
    • Build the floor by hand out of allowed materials, then run /bp generate lobby1 is still required once so BlockParty captures/serializes the exact layout it should restore each round (BlockParty does not scan the world every round — it restores from the saved layout for performance and determinism).
  8. /bp info lobby1 to confirm there are no validation errors.
  9. /bp enable lobby1.
  10. Players run /bp join lobby1. Once min-players is reached the countdown starts automatically; joining an arena mid-countdown is allowed by default (allow-join-while-waiting: true).

Floor selection details

  • pos1 / pos2 define the two opposite corners of the rectangular floor region (any Y).
  • setfloor only changes which materials are allowed to be used/regenerated — it does not touch blocks in the world.
  • generate is the step that actually writes a random layout (biased evenly across the configured palette) across the whole region and serializes it into the arena's yml file (generated-layout) so it can be restored exactly, every round, without re-scanning or re-randomizing the world.

Player usage

  • /bp join <arena> to enter the waiting lobby. Your inventory, armor, offhand, health, food, XP, game mode, flight state, location and potion effects are all captured and will be restored exactly when you leave, get eliminated-and-the-match-ends, or the match ends.
  • /bp leave at any time to exit and be restored.
  • During a round, a title/subtitle/action bar/sound announce the target color, and the target block is placed in your hotbar (slot 9) as a visual reminder. A boss bar (if enabled) shows the remaining time as a shrinking progress bar.
  • Get eliminated by not standing on the target color when the floor clears, or by falling off entirely. Eliminated players become spectators at the configured spectator location.
  • Last player standing wins; rewards, stats and celebration effects (fireworks, titles, sounds) fire automatically.

Configuration overview

  • config.yml — global settings: ui.* toggles for scoreboard/bossbar/titles/actionbar, sounds.* (Bukkit Sound enum names; invalid names are logged and skipped, never crash the plugin), performance.floor-blocks-per-tick (batch size for floor mutations), defaults.* (used only when /bp create seeds a new arena), default-floor-materials (the full 16-color concrete palette by default), rewards.winner.commands, and integrations.placeholderapi.
  • messages.yml — every user-facing string, in MiniMessage format (Adventure, bundled with Paper). Placeholders like %player%, %arena%, %round%, %time%, %color% are substituted per-message.
  • arenas/<name>.yml — one file per arena; a broken file only disables that one arena (the rest still load) and the error is logged.

Reload behavior

/blockparty reload re-reads config.yml, messages.yml, and every arena file. Arenas currently in the RUNNING or ENDING state are skipped during arena reload (their config keeps running unmodified) to avoid corrupting an active match; a warning is logged per skipped arena. Arenas that are WAITING, STARTING or DISABLED are reloaded fully from disk. This is a deliberate design choice: rather than queuing a reload for when the arena goes idle, in-progress matches simply finish on their old configuration and pick up the new configuration the next time they return to WAITING.

Rewards

rewards:
  winner:
    commands:
      - "eco give %player% 100"
      - "say %player% won BlockParty in %arena% after %round% rounds!"

Commands run as the console, so no Vault/economy plugin is required by BlockParty itself — if you reference an economy command (like eco give) you need that plugin installed separately. %player%, %arena% and %round% are replaced before dispatch.

PlaceholderAPI support

If PlaceholderAPI is installed, BlockParty registers a %blockparty_...% expansion automatically (soft-dependency — startup never fails if PAPI is absent):

  • %blockparty_wins%
  • %blockparty_games_played%
  • %blockparty_best_round%
  • %blockparty_arena%
  • %blockparty_players_<arena>%
  • %blockparty_state_<arena>%

Building from source

./gradlew clean build

The shaded plugin jar (with sqlite-jdbc bundled and relocated) is produced at build/libs/BlockParty-<version>.jar.

Run unit tests only:

./gradlew test

Unit tests cover the pure-logic package (us.tss3.blockparty.logic) with no Bukkit dependency: arena state transitions, countdown start/cancel logic, round-time progression/clamping math, target-color selection (deterministic via an injectable RNG), elimination/winner determination, arena config validation, and player-count/join logic.

Troubleshooting

  • "Arena failed validation" on enable — run /bp info <arena> to see exactly which fields are missing (lobby/spawn/spectator/region/materials/etc).
  • World unloaded warning — if an arena's world is unloaded while the plugin is running, BlockParty detects it, safely disables that arena and restores any players inside it.
  • Invalid sound/material in config — logged as a warning at startup/use and skipped; it will not crash the plugin.
  • Nothing happens on /bp join — check the arena is enabled (/bp info <arena>), not full, and that you are not already in another arena (/bp leave first).
  • Floor doesn't look right — remember setfloor only changes the allowed palette; you must run /bp generate <arena> to actually (re)generate and persist a layout.

Architecture

  • logic/ — pure, Bukkit-free game logic (unit tested).
  • arena/Arena (per-arena runtime state machine + round loop) and ArenaManager.
  • config/ArenaConfig, ArenaConfigLoader, ConfigManager, MessagesManager.
  • floor/FloorManager, tick-batched floor generation/removal/restoration.
  • session/PlayerSession, SessionManager (single-arena-membership enforcement).
  • model/PlayerState snapshot/restore.
  • command/BlockPartyCommand (single entry point, dispatches to handlers).
  • listener/ — connection/quit handling and gameplay restrictions.
  • scoreboard/ — interval-based sidebar scoreboard.
  • reward/ — console-command reward dispatch.
  • persistence/ — async SQLite-backed stats (StatsDatabase, StatsManager).
  • placeholder/ — optional PlaceholderAPI expansion, loaded only when PAPI is present.
  • util/ — sound/location helpers.
S
Description
No description provided
Readme
230 KiB
Languages
Java 90.5%
HTML 9.5%