
MatchboxPlugin
Matchbox is a social deduction game where 7 players work together to identify and eliminate the impostor (Spark) before it's too late. Every player looks identical, and the Spark must eliminate others without being caught.
A quick hotfix fixing a bug with the nick feature, it now consistently work throughout the entire game
Matchbox 0.9.7 - Community Edition! 🎉
Today we are shipping Matchbox 0.9.7 as a stable release.
This update focuses on three things:
- Better map setup flow for admins and map makers
- Stronger session observability for debugging and integrations
- Higher production confidence through test and CI hardening
Highlights
- New world-local setup workflow centered on setup commands
- Structured session flow logging for game lifecycle visibility
- Session statistics and timeline access improvements in the API
- Deterministic role assignment extension points
- Session-scoped ability handler extension hooks
- Documentation refresh across setup, operations, and release-readiness guides
Admin and Map Maker Improvements
- Setup flow now supports map initialization, validation, spawn setup, and seat setup in a more guided process
- Map geometry is managed with world-local configuration for cleaner multi-world operation
- Setup diagnostics and validation are easier to run before opening games to players
API and Integration Notes
- API surface has expanded around game logs, session logs, and game statistics snapshots
- Extension seams were added for custom role assignment and ability handling
- Session behavior is now easier to inspect and reason about during active matches
Quality and Stability
- Full build, check, and coverage verification gates are green
- CI pipeline is aligned with Java 21 and release flow expectations
- Deprecated API usage was cleaned up in core areas to reduce maintenance risk
Release Status
Matchbox 0.9.7 is marked stable and ready for production servers.
If you are updating from earlier 0.9.x releases, we recommend:
- Reviewing your map setup process with the setup tooling
- Running setup validation once per map world
- Confirming your admin command routines against the current docs
Thanks to everyone testing, reporting edge cases, and helping shape this release.
Matchbox 0.9.6 - Nick System, Sign Mode, Skin & Stability
Nick System
Players can now compete under custom nicknames that activate when a game starts and are removed the moment it ends. Nicks are session-scoped, unique per session, and persist as a preference across restarts.
/mb nick <name>- set a nick (3-16 chars, letters/numbers/_/-)/mb nick random- generate a realistic-looking random username/mb nick reset- remove your nick- Admins (
matchbox.admin) can set, randomise, or reset any player's nick - Action bar reminder shows your active nick while outside a game
Sign Mode
When
sign-mode.enabled: true, players communicate by placing signs during the swipe phase instead of typing in chat. Each player receives a sign kit at swipe start; all placed signs are automatically cleaned up when discussion begins or the game ends. Normal chat is suppressed while sign mode is active.Skin & Visual Changes
- Skin rendering upgraded to use ProtocolLib player-info packet rewrites for more consistent updates across clients
- Steve fallback improved - all players receive a consistent classic Steve skin when lookups fail (offline mode or API unavailable)
- Paper compatibility raised to 1.21.11
Bug Fixes
- Eliminated players no longer appear in game chat (cache was not cleared on death)
- Arrow tracking is now per-session - a round reset no longer affects players in other concurrent sessions
- Players with failed state backups are now excluded from the game entirely rather than being left in a broken state
- Win screen now correctly shows the Spark's display name instead of their UUID on disconnect
- Delusion decay timer is now cancelled on session end
- Random skin preloading no longer silently fails on malformed UUIDs
- Hologram cleanup is safe during plugin shutdown - no new scheduler tasks are created while disabling
- Session player limit fixed - min/max validation now accepts the full
2-20range - Default config spawn world corrected from
m4tchb0xtypo tom4tchbox
Matchbox Update: v0.9.5 is here!
This is a safe, behind-the-scenes update no gameplay changes, just better stability and new tools for the future!
Updating is 100% safe and recommended.
What's new in this release:
- New Matchbox API – lets other plugins connect smoothly (big step for future features!)
- New Javadocs + Public Docs – grab the JavaDocs JAR from the repo or view the live docs at https://ohacd.github.io/MatchboxPlugin/
- Better spectator chat – alive players & spectators now have separate chats
- Fixed arrow hits – decorated pots are now fully protected during games
- Improved stability – faster sessions, better error handling, and heavy testing
Full changelog in the project's repo.
Thanks for playing!
[0.9.4] - Latest Release (Ability System)
This stability release marks the end of the rapid iteration phase for the plugin. It's mostly an under-the-hood update, modularizing the project and extending the last update's Spark ability system to also fit the medic (supporting future ability additions).
There is also a new ability for the spark
Delusion, which is a fake infection that stays for 30 seconds after application, that the medic can see.Other additions mainly focus on stability and ensuring the game is fully playable with all features working as intended (The infamous buggy Steve skin override).
Lastly, there has been an update to the default config, setting the random skin toggle to false by default and setting the Steve skin toggle to true by default.
Added
- Medic Secondary Ability System: Medic now uses the same ability system as Spark
- Healing Sight is now tracked as a secondary ability (preparing for future abilities)
- System modeled after the Spark secondary ability system for consistency
- Configurable via
medic.secondary-abilityin config.yml - Options: "random" (default), "healing_sight"
- Ready for future medic abilities to be added
- Delusion Ability: New Spark secondary ability that creates fake infections
- Spark can activate an 8-second window, then right-click a player to apply a fake infection
- Fake infections appear identical to real infections to the medic (same particles)
- Medic can see delusion infections using Healing Sight alongside real infections
- Medic can cure delusion infections, wasting their cure on a non-infected player
- Delusion infections automatically decay after 30 seconds
- Delusion infections do not cause elimination when discussion phase starts
- Configurable via
spark.secondary-abilityin config.yml - Options: "random" (default), "hunter_vision", "spark_swap", "delusion"
Changed
- Medic Ability System Architecture: Refactored medic abilities to match Spark's system
- Created
MedicSecondaryAbilityenum for ability tracking - Added ability selection logic in GameManager
- Updated InventoryManager to handle medic abilities dynamically
- MedicSightListener now checks if ability is active before allowing use
- System is now extensible for adding new medic abilities in the future
- Created
- Config steve skin override: Default config now comes with steve skin override as true by default
- Random skin toggle is now set to false by default
- Debug command: Fake infected (Delusion infection) is tracked by the debug command
- Added the fake infected param to
/matchbox debugcommand
- Added the fake infected param to
Fixed
- Steve Skin Override: Fixed inconsistent steve skin application
- All players now consistently receive steve skins when enabled
- Skins are reapplied at the start of each new round to ensure consistency
- Fixed issue where some players would get alex or random skins instead of steve
- Invalid default seat locations: Fixed an error where default seat locations weren't loading correctly when used with the
m4tchb0xmap- Default Spawn/Seat locations are no longer linked to a world folder named
world - Now linked to a world folder named
m4tchb0x
- Default Spawn/Seat locations are no longer linked to a world folder named
- Medic Secondary Ability System: Medic now uses the same ability system as Spark
[0.9.3] - Latest Release (It's the little quirks in life)
Added
- Spark Secondary Ability System: Spark now rolls a secondary ability each round
- Hunter Vision or Spark Swap, alongside Swipe
- Spark Swap occupies the Hunter Vision slot (slot 28) when selected
- Spark Swap teleports with preloaded chunks, preserved velocity, and preserved look direction (designed to be invisible)
- Dynamic Voting Threshold System: Voting thresholds now scale dynamically based on alive player count
- Logarithmic scaling between key points: 20 players (20%), 7 players (30%), 3 players and below (50%)
- Works for 2-20 players with smooth threshold transitions
- Threshold display shown during voting phase: "Threshold: X/Y" (required votes / alive players) (Dantizzle)
- Voting Penalty System: Penalty applied when voting phases end without elimination
- Each phase without elimination reduces the threshold by ~3.33% (configurable)
- Maximum penalty of 10% after 3 consecutive no-elimination phases
- Penalty resets when a successful elimination occurs
- Enhanced Tie Handling: Ties are now checked against the dynamic threshold
- If tie vote count doesn't meet threshold: no elimination occurs
- If tie vote count meets threshold: random player from tie is eliminated
- Voting Configuration: All voting threshold values are now configurable in
config.ymlvoting.threshold.at-20-players- Threshold percentage at 20 players (default: 0.20)voting.threshold.at-7-players- Threshold percentage at 7 players (default: 0.30)voting.threshold.at-3-players- Threshold percentage at 3 players and below (default: 0.50)voting.penalty.per-phase- Penalty percentage per phase without elimination (default: 0.0333)voting.penalty.max-phases- Maximum phases that accumulate penalty (default: 3)voting.penalty.max-reduction- Maximum penalty reduction percentage (default: 0.10)
- Spark Ability Configuration: Spark secondary ability selection is now configurable
spark.secondary-ability- Choose Spark ability: "random" (default), "hunter_vision", or "spark_swap"- When set to "random", ability is randomly selected each round (default behavior)
- When set to a specific ability, that ability is always used
Changed
- Ability System Routing: Ability system routing remains unified; Spark inventories are rebuilt each swipe phase with the chosen secondary
- Voting Phase Display: Actionbar now shows both countdown timer and threshold requirement
- Format: "Voting: Xs | Threshold: Y/Z" (timer and required votes / alive players)
- Updates every second alongside the countdown timer
- Voting Phase Instructions: Improved voting phase start messages
- Removed counter-intuitive "right-click player while holding paper" instruction
- Added information that players can choose to not vote
- Added threshold requirement display in title subtitle
- Added explanation that no elimination occurs if threshold isn't met
- Phase Visuals: Skins are no longer reset to original during discussion/voting, and nametags remain hidden in those phases
- Players keep their assigned game skins across phases until swipe starts again
- Nametags stay hidden during discussion and voting (revealed only on elimination)
- Vote Resolution: Voting now requires meeting the dynamic threshold instead of simple majority
- Players see clear feedback when threshold isn't met
- System tracks consecutive no-elimination phases for penalty calculation
Fixed
- Steve skin override:
cosmetics.use-steve-skinsnow correctly applies Steve skins to players (Dantizzle)
- Spark Secondary Ability System: Spark now rolls a secondary ability each round
[0.9.2] - Latest Release (It's all about the base)
This is a small patch that focuses on cleanup/QOL features and insuring everything works as intended. Due to how Skins are currently handled, the steve skin override falls back to using Alex/Steve skins depending on the player model, this will hopefully be handled better next update.
Added
- Cleaner version handling/project status handling: Project status and versioning are now handled dynamically
- The player will get notified if a newer version is available for the plugin
- Under the hood cleanup for dynamic project status display and project versioning/version checking
- Pre-discussion elimination notice: Eliminations are now announced as titles 10 seconds before teleporting to discussion
- Uses the MessageUtils title pipeline, matching other UI
- Applies blindness and heavy slowness during the 10s hold, cleared on teleport
- Works alongside seat teleports and discussion timers
- Nickname support: Voting papers, elimination titles, and hologram reveals now use display names with UUID-backed targeting to remain compatible with nick plugins (Dantizzle)
- Debug force start:
/matchbox debugstart <session>lets admins start a game with fewer than the configured minimum players (still enforces spawn/seat validity)
Fixed
- Steve skin override:
cosmetics.use-steve-skinsnow reapplies Steve skins for gameplay while restoring players’ original skins during discussion (no more partial overrides), currently falls back to Alex skin; will be fixed in the next update (Dantizzle) - Location listing clarity:
/matchbox listspawnsand/matchbox listseatspawnsnow display all configured entries and mark any with missing/not-loaded worlds instead of reporting none exist
- Cleaner version handling/project status handling: Project status and versioning are now handled dynamically
[0.9.1] - Latest Release (Config and QOL update)
Added
- Config File Support: Full configuration system with
config.yml- Configurable phase durations (swipe, discussion, voting)
- Configurable player limits (min/max players per session)
- Configurable seat spawn numbers for discussion phase
- Random skins toggle (enable/disable)
- Seat Location System: Discussion phase seat spawns
- Set seat locations via
/matchbox setseat <number>command (saves to config) - List seat locations via
/matchbox listseatspawnscommand - Remove set seat locations via
/matchbox removeseat <number>command - Configure seat coordinates in config file
- Players automatically teleported to seats during discussion
- Set seat locations via
- Spawn Location Configuration: Game spawn locations in config
- Set spawn locations via
/matchbox setspawncommand (saves to config) - List spawn locations via
/matchbox listspawns - Remove set spawn locations via
/matchbox removespawn <index> - Configure spawn coordinates in config file
- Automatic loading from config when sessions don't have locations
- Set spawn locations via
- Skin Restoration System: Enhanced skin management
- Player skins return to normal during discussion phase
- Assigned skins restored after discussion ends
- Damage Protection: Players are invulnerable during active games
- All damage sources blocked (hits, lava, fall damage, etc.)
- Arrows hit players (for nametag revelation) but deal no damage
- Death prevention during games
- Hunger loss prevention
- Block Interaction Protection: Block interactions disabled during games
- Right-click and left-click on blocks blocked
- Item interactions still work (abilities, voting)
- Config Validation: Added bound checks to all config values
- Phase durations: Swipe (30-600s), Discussion (5-300s), Voting (5-120s)
- Player limits: Min (2-7), Max (2-20) with cross-validation
- Min spawn locations: (1-50)
- Clear Commands: Added commands to clear all spawn/seat locations with confirmation
/matchbox clearspawns- Clear all spawn locations (requires confirmation)/matchbox clearseats- Clear all seat locations (requires confirmation)- Both commands require typing the command again with
confirmto execute
- Config Usage Notification: Players are notified when a game starts using config defaults
- Shows how many spawn and seat locations were loaded from config
- Helps players understand when config is being used vs session-specific settings
- Default Configuration: Plugin ships with complete default config for M4tchbox map
- 11 pre-configured spawn locations
- 8 pre-configured seat locations
- Optimized phase durations and player limits
- Ready to play immediately without setup
- Welcome Message System: Players receive a welcome message when joining the server
- Title animation welcoming players to Matchbox
- Information about the game, current version, and status
- Discord link for bug reports and suggestions (https://discord.gg/BTDP3APfq8)
- Steve Skins Option: Config option to use default Steve skins for all players
cosmetics.use-steve-skinsin config.yml- When enabled, all players get Steve skin regardless of random-skins-enabled setting
- Works alongside existing random skins system
- Gamemode Management: Players automatically set to Adventure mode during games
- Players set to Adventure mode when game starts
- Original gamemode restored when game ends
- Prevents block breaking and other survival interactions during gameplay
- Session Creation Broadcast: Upon new session creation via
/matchbox start <name>, a broadcast message is sent to all players- Informs players about the new session and how to join
- Encourages player participation and awareness of new games
Changed
- Location Management: Locations can be set via commands or config file
- Commands automatically save to config (config-first approach)
- Config locations used as defaults for new sessions
- Session-specific locations can still be set via
setdiscussioncommand
- setspawn Command: No longer requires session name - saves directly to config
- Usage:
/matchbox setspawn(was:/matchbox setspawn <session>)
- Usage:
- setseat Command: No longer requires session name - saves directly to config
- Usage:
/matchbox setseat <number>(was:/matchbox setseat <session> <number>)
- Usage:
- Phase Durations: All phase durations configurable via config file
- Default: Swipe (180s), Discussion (30s), Voting (15s)
- Player Limits: Min/max players configurable via config file
- Default: Min 2, Max 7 players
Fixed
- Spawn Location Loading: Fixed issue where config spawn locations weren't checked before requiring manual spawn setup
- Config spawns are now loaded first before checking if spawns are sufficient
- Players are notified when starting from config defaults
- Arrow Damage: Fixed arrows passing through players due to invincibility
- Arrows now properly hit players (for nametag revelation) but deal no damage
- Other damage sources remain blocked during active games
- Skin Manager: Improved offline mode compatibility
- Better error handling for players without valid skin data
- Graceful fallback when skin properties are missing
- Spawn Distribution: Ensured all config spawn locations are properly loaded and used
- Fixed issue where only 1 spawn location was used even when multiple were in config
- Fixed players spawning at same position when multiple players share one spawn location
- Session system cleanup and state management
- Deprecated method usage in leave command
- Discussion/seat location teleportation logic
- Player state restoration on game end
- All commands have been added to tab with proper permission checks
- Flower Pot Duplication Bug: Fixed exploit where players could duplicate flowers from flower pots
- All flower pot interactions (right-click) are now blocked during active games
- Prevents players from extracting and stacking flowers from flower pots
- Config File Support: Full configuration system with
Another Major update, skipping over to 0.9.0, check the changelog in the project's repository.
The project now depends on protocolLib for the custom Spark ability. Stick to using protocolLib for the time being, as I haven't tested much without it yet. This issue should be resolved to support both with protocolLib and without before the full release.
[0.9.0] - Latest
Added
- Global Swipe/Cure Indicators: The subtle particle cues for Spark swipes and Medic cures now broadcast to every nearby player, keeping spectators and recordings informed without exposing roles.
- Player-Focused Cure Notice: Cured players receive a direct chat message, so the announcement no longer conflicts with the discussion-phase titles.
- Hunter Vision Resilience: ProtocolLib Hunter Vision now uses the modern
DataValuepipeline, automatically falling back to the particle adapter whenever packet delivery fails.
Fixed
- Spark Disconnects: Resolved
clientbound/minecraft:set_entity_datacrashes that kicked Sparks whenever glow packets used the legacyDataItem. - Random Skin Preload: The curated skin pool now resolves Mojang UUIDs before requesting textures, eliminating the “Failed to fetch skin” spam and guaranteeing usable skins even on offline-mode servers. (Still needs testing, but functional)
Changed
- Version Jump: Skipped the remaining 0.8.x line to mark these stability upgrades as the start of the 0.9 series. Config support remains the final blocker for 1.0.
This is a major update that skips 0.8.5-beta - check the changelog in the mod repository to see the entire changelog for this update and 0.8.5-beta
[0.8.6-beta] - Latest
Fixed
- Double Round Messages: Fixed issue where players received two round messages (round 1 and round 2) when starting a game
- Removed duplicate
startNewRound()call inGameManager.startRound() - Round counter now correctly starts at 1 instead of jumping to 2
- Removed duplicate
- Session Cleanup & Termination: Fixed multiple session management issues
- Sessions are now fully removed from SessionManager when game ends (complete termination)
- Sessions properly terminated on game end - marked inactive and removed from SessionManager
- Fixed memory leak where valid waiting sessions were being deleted by list command
- Sessions are now only removed if they have 0 players (truly empty)
- Inactive sessions with players are now correctly shown as "[Waiting]" in list command
- Session List Command: Fixed critical bug where valid sessions were being removed from the list
- Sessions created with
/matchbox startnow properly appear in the list - Sessions persist until they're terminated or become empty
- Fixed session name display - now shows case-preserved names correctly
getAllSessionNames()now returns case-preserved session names instead of lowercase keys
- Sessions created with
- Inventory Protection: Fixed issue where inventory protection was active for all players, even when not in a game
- Inventory protection now only activates when player is in an active game session
- Players can now freely move items when not in a game
- Added
isPlayerInActiveGame()check to all protection event handlers GameItemProtectionListenernow requiresGameManagerto check player game state
- Spark Name Announcement: Fixed win message to include the Spark's player name
- Win messages now show:
"[PlayerName] (Spark) wins!"instead of just "Spark wins!" - Applies to all Spark win conditions
- Spark name is retrieved from UUID and displayed in all win scenarios
- Win messages now show:
- Voting Paper Activation: Enhanced voting paper interaction support
- Added left-click support in inventory (previously only right-click)
- Right-click in inventory still works
- Right-click when held in main hand still works (via VoteItemListener)
- Players can now vote using any of these methods
- VoteManager Logic: Fixed redundant vote count update logic
- Removed unreachable code that checked for previous vote targets
- Simplified vote registration logic for better performance
- NullPointerException in Listeners: Fixed critical bug where listeners crashed when no active sessions exist
VotePaperListenernow uses session-specific context instead of deprecatedgetPhaseManager()VoteItemListenernow uses session-specific context instead of deprecated methodsHitRevealListenernow uses session-specific context instead of deprecated methods- All listeners now properly check if player is in an active game before processing events
- Prevents crashes when players interact with items outside of active games
- Voting & Ability Activation: Enhanced activation methods for all papers
- Voting papers can now be activated via: right-click in inventory, left-click in inventory, or right-click when held in main hand
- Ability papers (Swipe, Cure, Hunter Vision, Healing Sight) can now be activated via: right-click in inventory, left-click in inventory, or right-click when held in main hand
- Fixed right-click on main hand for voting papers - now properly works when holding paper
- All activation methods now work consistently across all papers
- Visual Ability Indicators: Added visual feedback for used abilities and votes
- Used papers are now replaced with gray dye items showing "[USED]" status
- Gray dye maintains the same display name and lore as the original paper
- Provides clear visual indication that an ability/vote has been used this round
- Integrated seamlessly into existing logic without breaking functionality
- Game State Safety Checks: Enhanced all event listeners with comprehensive game state validation
- All action handlers now verify game is active before processing any game logic
- All ability listeners check
isGameActive()before allowing ability activation - All voting listeners check
isGameActive()before processing votes - All hit listeners check
isGameActive()before processing player interactions - Prevents game logic from executing when players are not in active games
- Prevents phase-specific logic from executing in wrong phases
- Ensures robust separation between active games and inactive players
Changed
- Session Termination: Sessions are now fully removed when game ends, not just marked inactive
- Ensures complete cleanup and prevents memory leaks
- Sessions automatically removed from SessionManager on game end
- No need to use
stopcommand for full session termination
- Voting Phase Instructions: Added helpful voting instructions during voting phase
- Players now receive clear instructions on how to vote when voting phase begins
- Instructions explain: right-click paper in inventory, left-click paper in inventory, or right-click player while holding their paper
- Helps players understand voting mechanics, especially useful with custom skins where names might not be visible
Code Quality & Documentation
- Code Cleanup: Comprehensive codebase cleanup and refactoring
- Removed non-essential comments ("NEW:", "Note:", "Edge case:", etc.)
- Removed obsolete TODO comments
- Cleaned up verbose inline comments that didn't add value
- Removed redundant code and dead branches
- Documentation Improvements: Enhanced code documentation
- Added comprehensive JavaDoc to main plugin class (Matchbox)
- Added detailed JavaDoc to enums (GamePhase, Role)
- Improved class-level documentation (SessionGameContext, etc.)
- Added proper @Deprecated annotations with migration guidance
- Enhanced field documentation with clear descriptions
- Code Quality: Improved code clarity and maintainability
- Removed dead code branches that could never execute
- Better organized event listener registration
- Improved error handling and logging
- Double Round Messages: Fixed issue where players received two round messages (round 1 and round 2) when starting a game
- Fixed a gamebreaking bug - items can no longer be moved inside the player's inventory during the game
Changelog:
-Fixed a bug where game sessions weren't terminating on game end
- Fixed a bug where the Role paper wasn't showing up in the player's inventory
Full game loop implemented

