This project was created entirely by AI.
Chinese documentation: README.zh-CN.md Chinese gameplay and operations wiki: docs/wiki.zh-CN.md Contributor notes: CONTRIBUTING.md
MahjongPaper is a Paper plugin rewrite of MahjongCraft built around:
- Paper display entities
- CraftEngine-managed resource bundle, custom items, furniture hitboxes, and culling integration
The current branch already supports playable Riichi Mahjong, GB Mahjong, and Sichuan Mahjong flows on Paper/Folia:
- lobby-style tables that can persist across restart
- empty-table creation, fixed east/south/west/north seats, click-to-join, and click-to-ready
- automatic round start once 4 seats are filled and all seated players are ready
- bots for unattended seats, with bots treated as ready by default
- table-owner permissions plus a table control GUI for common lobby actions
- leaving before the round starts, or deferred leave after the current hand ends
- dealing, drawing, discarding, riichi, tsumo, ron, chii, pon, minkan, ankan, and kakan
- opening dice roll animation and live public table state displays
- Riichi scoring through
mahjong-utils - GB Mahjong rule evaluation through the bundled JNI bridge and vendored
GB-Mahjongsource - spectator mode, private hand visibility, HUD overlays, and localized prompts
- Mahjong Soul-style rank persistence and per-mode leaderboards when database-backed ranking is enabled
- CraftEngine-backed seat/table interaction and CraftEngine bundle export
- round history persistence through H2 by default, with optional MariaDB/MySQL
- game room system: spatial containers for tables, with optional table creation restriction, enter/exit messages, and leave countdown for active matches
For normal server operation, create at least one game room before opening public tables. A game room is the allowed play area for Mahjong tables; when gameRooms.restrictNewTables is enabled, /mahjong create only works while the admin is standing inside a game room.
Quick tutorial:
- Give yourself admin permission:
mahjongpaper.admin. - Run
/mahjong room wandto get the selection wand. - Left-click one corner of the room, then right-click the opposite corner.
- Check the cyan particle outline and make sure the entire play area is inside the cuboid.
- Run
/mahjong room create main-hall Main Hall. - Stand inside that room and run
/mahjong createto place a Mahjong table. - Use
/mahjong room listand/mahjong room info main-hallto confirm the saved room.
If you only need a quick test room, stand at the room center and run /mahjong room create quick-room; without a wand selection, the plugin uses gameRooms.defaultRadius and gameRooms.defaultHeight.
For the longer operations guide, see Game room system in the Chinese wiki.
/mahjong help: show in-game command help/mahjong room wand: get the game-room selection wand/mahjong room create <id> [name]: create a game room from the current wand selection, or around your current position/mahjong room list: list saved game rooms/mahjong room info <id>: show a game room's world, bounds, size, and owner/mahjong create: create a new empty table at your location/mahjong botmatch [MAJSOUL_HANCHAN|MAJSOUL_TONPUU|GB|SICHUAN]: create a 4-bot test match and spectate it/mahjong mode <MAJSOUL_TONPUU|MAJSOUL_HANCHAN|GB|SICHUAN>: apply a preset before the next start/mahjong join <tableId>: join a table as a player/mahjong leave: leave immediately before the hand starts, or queue a leave after the current hand/mahjong list: list active tables and their locations/mahjong start: toggle ready status for your seat/mahjong spectate <tableId>: spectate a table/mahjong unspectate: stop spectating/mahjong table [tableId]: open the table control panel/mahjong table owner <player> [tableId]: transfer table ownership to a seated player/mahjong addbotand/mahjong removebot: table owner/admin commands to manage bots before the round starts/mahjong rule [key] [value]: open the rule GUI, or let the table owner/admin change rules before the next start- Riichi multi-ron mode:
/mahjong rule ronMode <HEAD_BUMP|MULTI_RON> - Riichi flow profile:
/mahjong rule riichiProfile <MAJSOUL|TOURNAMENT> /mahjong state: show the current table summary/mahjong riichi <index>,/mahjong tsumo,/mahjong ron,/mahjong pon,/mahjong minkan,/mahjong chii <tileA> <tileB>,/mahjong kan <tile>,/mahjong skip,/mahjong kyuushu: round actions/mahjong settlement: reopen the latest settlement UI/mahjong rank: show your Mahjong Soul-style rank summary when ranking is enabled/mahjong leaderboard [RIICHI|GB|SICHUAN]: show the ranked leaderboard for one mode/mahjong render,/mahjong clear,/mahjong inspect: table render maintenance and diagnostics/mahjong forceend [tableId]: admin command to stop a running match/mahjong deletetable [tableId]: admin command to delete a table/mahjong reload: admin command to reload configuration and re-render active tables
Admin targeting details:
forceendanddeletetableaccept an explicittableId- if omitted, they first try the table you are in or spectating
- if you are not attached to a table, they fall back to the nearest table within range
- On production servers, create the game room first, then stand inside it before running
/mahjong create. /mahjong createcreates an empty table only; it does not auto-seat the creator- the creator becomes the table owner and can manage rules, bots, refresh, start, and delete from
/mahjong table - the table owner/admin can transfer ownership with
/mahjong table owner <player> [tableId] - players join a fixed seat by interacting with that seat's floating label
- the same seat label is used to toggle ready before the match starts
- a round starts automatically only when all 4 seats are filled and all seated players are ready
- after a hand or a full match ends, players must ready again before the next start
- Riichi round flow rules: docs/riichi-round-flow.md
- GB Mahjong rule source: docs/gb-mahjong-rules.md
- Chinese gameplay and operations wiki: docs/wiki.zh-CN.md
- Newly created tables default to Mahjong Soul-style Riichi hanchan rules.
MAJSOUL_TONPUUandMAJSOUL_HANCHANare the primary presets; both use three red fives, open tanyao, multi-ron, and the Mahjong Soul kan-dora reveal profile.GBremains available as an optional ruleset, backed by the vendoredGB-Mahjongnative bridge.SICHUANis available as a suited-tile-only Bloody Battle ruleset.
The plugin ships three independent rulesets. Switch between them before a hand starts with /mahjong mode <MODE>. Each is explained below with concrete tile examples.
Every mode uses the same play loop:
- Create a game room first on production servers; then stand inside it and run
/mahjong createto create an empty table. - Click one of the east/south/west/north floating seat labels to sit down, or use
/mahjong join <tableId>. - Fill empty seats with
/mahjong addbot(bots count as ready). /mahjong starttoggles ready; the hand auto-starts once all 4 seats are filled and ready.- Discard: on your turn, click a tile in your hand to discard it.
- React to others: after someone discards, a reaction window opens. Use commands to call:
/mahjong pon,/mahjong chii <tileA> <tileB>(from the player to your left),/mahjong minkan/mahjong ron(win on a discard),/mahjong skip(pass)
- On your own turn:
/mahjong tsumo(self-draw win),/mahjong kan <tile>(closed or added kan). - A settlement screen pops up when the hand ends; reopen it with
/mahjong settlement.
Riichi-only commands:
/mahjong riichi <handIndex>(declare riichi and discard that tile) and/mahjong kyuushu(nine-terminals abortive draw on the first turn). Both work on Riichi tables only.
The primary mode, aimed at players familiar with Japanese / Mahjong Soul rules.
- Match length:
MAJSOUL_HANCHANis a half-game (East 1 through South 4, 8 hands);MAJSOUL_TONPUUis East-only (East 1 through East 4, 4 hands). - Points: everyone starts at 25,000 with a 30,000 return target; final placement is by score.
- Red fives: one red 5 each in man/pin/sou (3 total), each worth one dora.
- Winning floor: 1 han minimum, and you must have a yaku (open tanyao is enabled, so melded hands can still score).
- Riichi: declare when closed and the wall still has draws left; you pay 1000 points and may only discard the tile you just drew.
Example: you self-draw a red 5-man after declaring riichi.
Menzen tsumo (1 han) + Riichi (1 han) + your hand's yaku + red-five dora (1 han) ...
Stacking more yaku pushes the han higher; yakuman hands (kokushi, daisangen, etc.) pay a fixed large score. The appeal is betting on riichi, reading discards, and combining yaku.
China's official competition rules, the richest in fan types and the highest barrier. Switch with /mahjong mode GB.
- Tiles: man/pin/sou plus honor tiles (winds and dragons), with flower tiles (plum/orchid/bamboo/chrysanthemum) as bonus draws.
- Winning floor: 8 fan minimum — hands worth fewer than 8 fan cannot win. This is the biggest difference from the other modes.
- Scoring: fan accumulate per the official fan table; more fan means more points.
- Evaluation: fan are judged by the bundled
GB-Mahjongnative library, following the official interpretation strictly.
Example: you build "Half Flush + All Triplets".
Half Flush (6 fan) + All Triplets (6 fan) = 12 fan >= 8 fan -> win allowed
With only "All Triplets (6 fan)" you fall short of 8 fan and cannot win, so you must keep building toward a bigger hand. GB pushes you toward complex, high-value hands — ideal for players who want depth.
A fast, intense regional style. Switch with /mahjong mode SICHUAN.
- Suited tiles only: man/pin/sou, no honor tiles and no flowers.
- Missing-a-suit (ding que): your winning hand must drop one entire suit (e.g. only man and pin, zero sou tiles).
- Bloody battle (xue zhan dao di): a win does not end the hand immediately. Winners step out and the rest keep playing until the third player also wins, then the whole hand settles. So a single hand can produce up to 3 winners.
- Any-fan win: unlike GB's 8-fan floor, Sichuan lets you win once you complete a basic shape.
- Fan cap: capped at 5 fan (32x scoring).
Main fan types:
| Fan | Value | Notes |
|---|---|---|
| Chicken Hand | 1 | basic shape |
| All Triplets | 1 | all triplets (pon/kan) |
| Full Flush | 2 | one suit only |
| Seven Pairs | 2 | seven pairs |
| Dragon Seven Pairs | 3 | seven pairs with 1 "root" (four identical) |
| Double Dragon Seven Pairs | 4 | seven pairs with 2 roots |
| Deluxe Dragon Seven Pairs | 5 | seven pairs with 3 roots (cap) |
| All 2-5-8 Pairs | +2 | every tile is 2/5/8 (stacks with all-triplets or seven pairs) |
| Root | +1 each | each kong adds one fan |
| Golden Hook | +1 | all-triplets waiting on a single pair tile |
| Under the Sea / Kong Bloom / Robbing the Kong, etc. | +1 | special winning methods |
Example: you drop sou, build a full-flush seven-pair hand, and one set is four pin tiles (1 root).
Full Flush (2 fan) + seven pairs upgraded to Dragon Seven Pairs (3 fan, includes 1 root) = 5 fan -> capped, scored at 32x
Scoring: fan map to a base of
.\gradlew.bat buildThe plugin currently declares CraftEngine as a required dependency in plugin.yml, so CraftEngine must be present at runtime.
The default config lives at src/main/resources/config.yml.
The current human-friendly layout is:
database.connection: database type and MariaDB/MySQL connection targetdatabase.credentials: MariaDB/MySQL username and passworddatabase.h2: local embedded H2 settingsdatabase.pool: connection pool sizingtables.persistence: persistent table restore filegameRooms: game room system — spatial containers for tables, creation restriction, enter/exit messages, and leave countdownranking: Mahjong Soul-style room presets and rank persistenceintegrations.craftengine: CraftEngine export and interaction preferencesdebug: debug logging switches
Notes:
- configuration is snapshotted on load
/mahjong reloadreloads config, rebuilds CraftEngine bridges, and re-renders active tables- older flat keys are still accepted for backward compatibility
When CraftEngine is installed, MahjongPaper exports a bundle to:
plugins/CraftEngine/resources/mahjongpaper
The exported bundle includes:
pack.ymlconfiguration/items/mahjong_tiles.ymlresourcepack/assets/mahjongcraft/...
MahjongPaper currently uses CraftEngine for:
- custom mahjong tile items
- table and seat hitbox furniture
- tracked entity culling integration
- furniture interaction routing for table interaction
The assets in resourcepack are packaged and delivered through the exported CraftEngine bundle.
MahjongCraft: https://github.com/EndlessCheng/MahjongCraftMahjongPlay: https://github.com/7yunluo/MahjongPlaymahjong-utils: https://github.com/ssttkkl/mahjong-utilsPaper: https://papermc.io/software/paperCraftEngine: https://github.com/Xiao-MoMi/craft-engineGB-Mahjong: https://github.com/zheng-fan/GB-Mahjongmahjong_graphic: https://github.com/lietxia/mahjong_graphic
- Contributing guide: .github/CONTRIBUTING.md
- Code of conduct: .github/CODE_OF_CONDUCT.md
- Security policy: .github/SECURITY.md
- Support: .github/SUPPORT.md
This project is licensed under the MIT License.