Official Guide

Guides & reference

Explore the complete guides and reference material below for RankForge.

๐Ÿ“ Full Configuration Examples

Survival Server (5 Ranks)

Click to expand
# ranks.yml
default-rank: Guest

ranks:
  Guest:
    display-name: "&7[Guest]"
    next-rank: "Member"
    slot: 10
    material: GRAY_WOOL
    lore:
      - "&7Welcome to the server!"
    chat-prefix: "&7[G]"
    permissions: []
    commands: []
    required-money: 0
    required-xp-level: 0
    required-playtime: 0
    required-mob-kills: 0
    required-block-breaks: 0
    required-items: {}

  Member:
    display-name: "&a[Member]"
    next-rank: "Veteran"
    slot: 13
    material: GREEN_WOOL
    lore:
      - "&7A trusted member."
      - ""
      - "&eRequires:"
      - "  &7$500 | 5 XP | 1 hour"
    chat-prefix: "&a[M]"
    permissions:
      - "essentials.sethome.multiple.2"
    commands:
      - "lp user %player% group set member"
      - "eco take %player% 500"
    required-money: 500
    required-xp-level: 5
    required-playtime: 60
    required-mob-kills: 0
    required-block-breaks: 0
    required-items: {}

  Veteran:
    display-name: "&2[Veteran]"
    next-rank: "Elite"
    slot: 16
    material: EMERALD
    lore:
      - "&7A seasoned player."
    chat-prefix: "&2[V]"
    permissions:
      - "essentials.sethome.multiple.4"
    commands:
      - "lp user %player% group set veteran"
      - "eco take %player% 10000"
      - "give %player% GOLDEN_APPLE 3"
    required-money: 10000
    required-xp-level: 30
    required-playtime: 600
    required-mob-kills: 200
    required-block-breaks: 10000
    required-items:
      DIAMOND: 5

  Elite:
    display-name: "&b[Elite]"
    next-rank: "Legend"
    slot: 22
    material: DIAMOND
    lore:
      - "&7Among the best."
    chat-prefix: "&b[E]"
    permissions:
      - "essentials.sethome.multiple.6"
    commands:
      - "lp user %player% group set elite"
      - "eco take %player% 50000"
    required-money: 50000
    required-xp-level: 60
    required-playtime: 3000
    required-mob-kills: 1000
    required-block-breaks: 100000
    required-items:
      DIAMOND: 32
      NETHERITE_INGOT: 2

  Legend:
    display-name: "&6&l[Legend]"
    next-rank: ""
    slot: 31
    material: NETHER_STAR
    lore:
      - "&6The highest rank."
      - "&7Only the truly dedicated reach this."
    chat-prefix: "&6&l[L]"
    permissions:
      - "essentials.sethome.multiple.10"
    commands:
      - "lp user %player% group set legend"
      - "eco take %player% 200000"
      - "broadcast &6โœฆ %player% &rhas become a LEGEND! &6โœฆ"
    required-money: 200000
    required-xp-level: 100
    required-playtime: 10000
    required-mob-kills: 5000
    required-block-breaks: 500000
    required-items:
      NETHERITE_INGOT: 10
      DRAGON_EGG: 1
    required-quests:
      - "ender_dragon"

Prison Server (Aโ†’Z)

Click to expand
# ranks.yml
default-rank: A

ranks:
  A:
    display-name: "&7[A]"
    next-rank: "B"
    slot: 0
    material: GRAY_WOOL
    lore: ["&7Mine the A mine."]
    chat-prefix: "&7[A]"
    permissions: ["mines.a"]
    commands: []
    required-money: 0
    required-xp-level: 0
    required-playtime: 0
    required-mob-kills: 0
    required-block-breaks: 0
    required-items: {}

  B:
    display-name: "&f[B]"
    next-rank: "C"
    slot: 1
    material: WHITE_WOOL
    lore: ["&7Mine the B mine."]
    chat-prefix: "&f[B]"
    permissions: ["mines.b"]
    commands:
      - "lp user %player% group set B"
      - "eco take %player% 5000"
    required-money: 5000
    required-xp-level: 0
    required-playtime: 0
    required-mob-kills: 0
    required-block-breaks: 500
    required-items: {}

  # ... repeat the pattern through Z ...

  Z:
    display-name: "&6&l[Z] FREE"
    next-rank: ""
    slot: 25
    material: GOLD_BLOCK
    lore:
      - "&6You've earned your freedom!"
    chat-prefix: "&6[FREE]"
    permissions: ["mines.free", "prison.free"]
    commands:
      - "lp user %player% group set free"
      - "eco take %player% 10000000"
      - "broadcast &6%player% has earned their FREEDOM from prison!"
    required-money: 10000000
    required-xp-level: 0
    required-playtime: 0
    required-mob-kills: 0
    required-block-breaks: 1000000
    required-items: {}

๐Ÿ’ก Best Practices

Rank ID Naming

  • Use PascalCase or UPPERCASE: Guest, Member, Veteran or RANK_A, RANK_B
  • Avoid spaces and special characters
  • Keep IDs short โ€” they appear in logs, commands, and API calls

Requirement Scaling

  • Scale requirements exponentially, not linearly. Each rank should be noticeably harder than the last
  • Combine multiple requirement types to prevent any single grind path from being exploitable (e.g., money + playtime together prevent AFK farming)
  • Use required-block-breaks on survival/skyblock servers; use required-mob-kills on combat servers

LuckPerms Groups

  • Create a matching LuckPerms group for every rank before configuring RankForge
  • Use commands entries to call lp user %player% group set <group> โ€” this is permanent, unlike the permissions field which is session-based

YAML Editing Safety

  • Always run /rank reload after editing ranks.yml, never /reload
  • Use a YAML validator before applying changes on a live server
  • Take a backup of ranks.yml before major restructuring

MySQL on Networks

  • Use MySQL if you run more than one server (BungeeCord/Velocity) and want shared rank data
  • Ensure the MySQL user has only SELECT, INSERT, UPDATE, DELETE on the rankforge database (no DROP or CREATE)

โ“ Frequently Asked Questions

Why isn't my rank saving between restarts?

If using YAML storage, ensure the server is shutting down gracefully (not SIGKILL). RankForge performs a synchronous flush on onDisable(). If the server is killed abruptly, the last sync interval's changes may be lost. Use MySQL for stronger durability guarantees.

The money requirement isn't being checked.

Vault must be installed and an economy plugin must be registered with it. Check the startup log:

[RankForge] [SoftDep] Vault=โœ“ ...

If Vault shows โœ—, install Vault. If Vault shows โœ“ but economy is still not working, check whether your economy plugin registers with Vault on startup.

Permissions aren't being applied on login.

The permissions field grants session-based permissions. With LuckPerms, these are applied as transient nodes when the player joins. Check:

  1. LuckPerms shows โœ“ in the startup log
  2. The permission node in permissions is correctly spelled
  3. There are no LuckPerms policy restrictions blocking transient nodes

For permanent permissions, use commands with lp user %player% permission set <node> true.

Players can't rank up even though they meet all requirements.

Run /rank requirements as the player to see which requirements are unmet. Also check:

  • The next-rank field on their current rank is set correctly
  • The player's rank ID exists in ranks.yml
  • debug: true in config.yml for detailed logs
%rankforge_*% placeholders show as literal text.

PlaceholderAPI must be installed. Check the startup log for PlaceholderAPI=โœ“. If PAPI is installed but placeholders still don't resolve, run /papi reload and verify the plugin that uses them supports PAPI (check its documentation).

My rank GUI is blank / shows wrong items.

Each rank's icon is determined by its material field. If an invalid material name is used, the item defaults to GRAY_WOOL. The slot field must be unique per rank (0โ€“53). Run /rank editor drag to visually verify and correct slot assignments.

Block breaks aren't being counted.

RankForge's BlockBreakTracker uses a BlockBreakEvent listener. Ensure no other plugin is cancelling this event before RankForge processes it. In debug: true mode, block break events are logged for each player.

Can I have the same player on multiple rank systems?

RankForge uses a single linear rank chain. If you need separate progression paths (e.g., survival and donor), create distinct rank IDs and manage them via separate commands entries and LuckPerms groups. Multi-track support is not built in but can be simulated via the API.


๐Ÿ” Troubleshooting

Enable Debug Mode

# config.yml
debug: true

Reload with /rank reload. Debug mode prints detailed logs for:

  • Requirement checks per player
  • Block-break counter updates
  • Cache hits/misses
  • Storage read/write operations
  • Performance mode transitions

Common Errors

Error MessageCauseFix
[SoftDep] Vault=โœ—Vault not installedInstall Vault
[DB] Defaulting to fallback local storageMySQL connection failedCheck config.yml credentials; verify MySQL is running
[RankYaml] Failed to save ranks.ymlFile permissions issueCheck the server process has write access to plugins/RankForge/
Unknown subcommandTypo in commandRun /rank help to see all valid subcommands
Rank 'X' does not existRank ID not found in ranks.ymlCheck spelling; run /rank reload after adding the rank
[Requirements] Unknown statisticInvalid required-statistic-idCheck the Bukkit Statistic enum name (must be uppercase, untyped)
[AntiAbuse] Macro-like click detectedPlayer clicking GUI too fastNormal if player has no macro; report if persistent on legitimate players

Checking the Startup Log

A healthy startup looks like:

[RankForge] [SoftDep] Vault=โœ“  LuckPerms=โœ“  PlaceholderAPI=โœ“  Floodgate=โœ—
[RankForge] [Lang] Dynamically indexed 4 language profiles: [en, es, fil, id]
[RankForge] [REST] API server listening on port 4567   โ† (if enabled)
[RankForge] RankForge v3.8 successfully loaded! (5 ranks compiled)

If the rank count shows (0 ranks compiled), ranks.yml failed to parse. Check for YAML syntax errors (indentation, missing colons, tab characters).

Checking Player Data

Use /rank debug (run as the player) or the Player List GUI (/rank playerlist) to inspect a player's current rank, XP, and cached data.


๐Ÿค Contributing

Contributions are welcome! Please follow these steps:

  1. Fork the repository on GitHub
  2. Branch from main: git checkout -b feature/my-feature
  3. Code your changes following the existing style (Java 21, no wildcard imports, Javadoc on all public API methods)
  4. Test on a local Paper 1.21.4 server
  5. Commit with a clear message: git commit -m "feat: add custom statistic requirement support"
  6. Open a Pull Request targeting main

Bug Reports

Use GitHub Issues. Include:

  • Server software and exact version (e.g., Paper 1.21.4 #123)
  • Java version (java -version)
  • Full error from logs/latest.log
  • Your config.yml and ranks.yml (remove credentials)
  • Steps to reproduce

๐Ÿ’ฌ Support

ChannelLink
๐Ÿ› Bug ReportsGitHub Issues
๐Ÿ’ก Feature RequestsGitHub Discussions
๐Ÿ“– Source Codegithub.com/JoshuaOP/RankForge

Before opening an issue, enable debug: true, reproduce the problem, and include the relevant log section. Issues without reproduction steps may be closed without resolution.


๐Ÿ“„ License

MIT License

Copyright (c) 2024 JoshuaOP

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.

See LICENSE for the full text.


๐Ÿ™ Credits

Name / ProjectRole
JoshuaOPAuthor & lead developer
Vault (MilkBowl)Economy abstraction API
LuckPerms (Luck)Permission management API
PlaceholderAPI (extended_clip)Placeholder framework
HikariCP (brettwooldridge)High-performance JDBC connection pooling
bStats (Bastian)Anonymous plugin analytics
Paper TeamHigh-performance Bukkit fork
CommunityBug reports, translations, feature suggestions

Behind the Scenes: Automatic Schema Handling

No manual configuration changes are ever required for playtime tracking. The playtime key in ranks.yml stays the same whether you use whole minutes or the new duration-string format:

  1. RankForge automatically keeps the YAML playerdata schema up to date, adding playtime: 0 to any record that doesn't already have it.
  2. For MySQL, a playtime_minutes column is added automatically via ALTER TABLE on startup if it doesn't exist.
  3. Any player without existing wall-clock playtime data starts at 0 real minutes and accumulates from that point onward.

Note: Legacy tick-based statistics are never used to back-fill wall-clock playtime. Servers that want to credit players for time already played can use an admin command or manually edit playerdata.yml. This is intentional โ€” converting approximate tick counts would propagate their inaccuracy.

Tips and Best Practices

  • Start low. Begin with shorter playtime requirements (30โ€“60 minutes) and increase them based on your player feedback.
  • Combine with other requirements. Playtime alone doesn't show engagement. Pair it with block-breaks or mob-kills for a richer progression curve.
  • AFK players. Playtime counts even while AFK. If you want to exclude AFK time, use a compatible AFK plugin that removes players from the server (which stops the timer), or use an activity-based requirement like block-breaks as the primary gate.
  • Test before going live. Use /rank set <yourself> <rank> and /rank progress to verify requirements display correctly.
  • Reload safely. Always use /rank reload โ€” never /reload. A server reload can corrupt the tracker's session state.

Troubleshooting Playtime

SymptomCauseFix
Playtime shows 0 for an existing playerNormal for a record with no prior wall-clock data โ€” accumulation begins freshNo action needed; time will accumulate naturally
Playtime not advancingPlaytimeTracker not initializedCheck console for errors on startup; use /rank version to verify plugin loaded
Playtime resets on relogData not saving before quitCheck storage errors in console; ensure playerdata.yml is writable
Requirement shows wrong timeStale cacheRun /rank reload to flush the cache
MySQL column missingVery old database, migration failedCheck console for [DB] Column migration check failed warnings

โ“ Frequently Asked Questions

General

Q: Does RankForge work without Vault, LuckPerms, or PlaceholderAPI? A: Yes. All three are optional. Without Vault, money requirements are skipped. Without LuckPerms, a Bukkit PermissionAttachment is used as fallback. Without PlaceholderAPI, the %rankforge_*% placeholders are simply unavailable.

Q: Can I have unlimited ranks? A: Yes. RankForge loads every rank defined in ranks.yml with no hardcoded limit.

Q: Does RankForge support Bedrock players (Geyser/Floodgate)? A: Yes. All storage and checks use UUID, not player name. The Bedrock prefix (. by default) is stripped from display names automatically.

Q: Will /reload (vanilla server reload) break the plugin? A: It can. Always use /rank reload instead. The vanilla reload can corrupt in-memory state and discard unsaved playtime data.

Playtime

Q: How is playtime measured? A: Using System.currentTimeMillis() โ€” real wall-clock time measured in milliseconds and stored as whole minutes. This is completely independent of server TPS.

Q: Does playtime count while the player is AFK? A: Yes, by default. The timer runs from join to quit regardless of activity. If you need AFK detection, use an external AFK plugin that disconnects inactive players, or gate progression on activity-based requirements like block-breaks.

Q: Why does a player show 0 playtime even though they've played before? A: This happens if a player's record predates wall-clock tracking being enabled on your server. The vanilla PLAY_ONE_MINUTE statistic (tick-based) is intentionally not used to back-fill this value, since it can be skewed by lag. Playtime accumulates accurately from that point onward.

Q: What happens to playtime if the server crashes? A: Playtime is periodically flushed to storage (every sync.interval-ticks, default 10 seconds). On a crash, up to 10 seconds of playtime may be lost. Clean shutdowns always flush everything before stopping.

Q: Can I manually set a player's playtime? A: Currently, this must be done by editing playerdata.yml while the server is stopped (or via a MySQL UPDATE). A /rank playtime set admin command may be added in a future version.

Q: My playtime requirement shows "0min" in /rank progress even though I've been online for an hour. A: This can happen if the tracker didn't initialize on join (e.g., the plugin reloaded while you were online). Rejoin the server โ€” the tracker will re-register your session start. If the issue persists, check console for errors.

Q: Does playtime in ranks.yml still work without changes? A: Yes. The configuration key is identical. No migration of ranks.yml is required โ€” only the underlying implementation changed.

Storage

Q: Which storage backend should I use? A: YAML is suitable for single servers. MySQL is recommended for networks, bungeecord/velocity proxies, or servers with more than a few hundred players. MySQL is also required if you want to query player data from external tools (dashboards, Discord bots, etc.).

Q: My MySQL connection fails. Will the server error out? A: No. RankForge automatically falls back to YAML storage when MySQL is unavailable, logs a single info-level message, and continues loading normally.

Q: How do I migrate from YAML to MySQL? A: Start the server with MySQL configured. RankForge will create the tables. Then manually export data from playerdata.yml and insert it into rf_players. A built-in migration tool may be added in a future version.


๐Ÿ”ง Troubleshooting

Plugin fails to load

  1. Check Java version: java -version must be 21 or higher.
  2. Confirm you are running Spigot or Paper 1.17+.
  3. Review the console for [SEVERE] messages from RankForge on startup.

Ranks not loading

  1. Ensure ranks.yml is valid YAML. Use yaml-online-parser.appspot.com to validate.
  2. Verify the default-rank value matches an actual rank key.
  3. Run /rank reload after editing the file.

/rank up does nothing

  1. Run /rank progress โ€” this shows which requirements are unmet.
  2. Confirm the current rank has a next-rank set.
  3. Ensure you are not at the final rank (empty next-rank).

Playtime not advancing

  1. Check startup log โ€” PlaytimeTracker registers on load. If there are errors, address them.
  2. Relog: the join event re-registers your session start.
  3. Check if /rank requirements shows a playtime line. If absent, the rank has playtime: 0 (no requirement).

Playtime not saving after restart

  1. Check write permissions on plugins/RankForge/data/playerdata.yml.
  2. Confirm no [YamlStorage] Failed to save errors appear in console.
  3. For MySQL: check for [DB] MySQL save failed warnings.

GUI not opening

  1. Ensure no other plugin is cancelling inventory open events.
  2. Check for GuiClickShieldManager warnings in console.
  3. Confirm the player has rankforge.rank.use permission.

LuckPerms permissions not applying

  1. LuckPerms must load before RankForge. Add depend: [LuckPerms] to LuckPerms's plugin.yml or ensure load order.
  2. Verify the permission nodes in ranks.yml are valid (no spaces, valid format).
  3. Use /rank set <player> <rank> to force a re-apply after fixing configuration.

MySQL tables not created

  1. Verify credentials in config.yml are correct.
  2. Ensure the database user has CREATE TABLE, ALTER, and INSERT privileges.
  3. Check console for [DB] Failed to create MySQL tables with the specific SQL error.


๐Ÿ› ๏ธ Setup & Configuration Guide

This guide walks through every step of installing and configuring RankForge from scratch.


๐Ÿ“ฅ Installation Guide

Step 1 โ€” Download RankForge

Download the latest RankForge-*.jar from the SpigotMC resource page.

Step 2 โ€” Install the plugin

Drop the JAR into your server's plugins/ folder:

server/
โ””โ”€โ”€ plugins/
    โ””โ”€โ”€ RankForge-3.8.jar

Step 3 โ€” Install optional dependencies

Install any of the following soft dependencies for additional features:

PluginPurpose
VaultMoney requirements and economy balance tracking
LuckPermsAutomatic permission group management on rankup
PlaceholderAPI%rankforge_*% placeholders in other plugins
Floodgate / GeyserBedrock crossplay player name handling
MySQL(Configure in config.yml) Persistent relational storage for networks

None are required โ€” RankForge works out of the box with no dependencies.

Step 4 โ€” Start the server

Start your server once. RankForge auto-generates all configuration files:

plugins/RankForge/
โ”œโ”€โ”€ config.yml
โ”œโ”€โ”€ ranks.yml
โ”œโ”€โ”€ gui.yml
โ””โ”€โ”€ lang/
    โ”œโ”€โ”€ en.yml
    โ”œโ”€โ”€ es.yml
    โ”œโ”€โ”€ fil.yml
    โ””โ”€โ”€ id.yml

Step 5 โ€” Configure the plugin

Edit the generated files (see the Configuration Guide below).

Step 6 โ€” Reload or restart

Apply your changes without a full restart:

/rank reload

Never use the vanilla /reload command. It can corrupt in-memory player data and break the playtime tracker. Always use /rank reload.


โš™๏ธ Configuration Guide

config.yml

The master settings file. Key sections:

SectionKeyDescription
languagedefaultDefault language code (en, es, fil, id)
languageper-playerAllow players to pick their own language
announcementsrankup.broadcastBroadcast message to all players on rankup
announcementsrankup.titleFull-screen title shown to the ranking-up player
cosmeticbossbar.enabledBoss bar on rankup and progress checks
cosmetictablist.enabledShow rank prefix in the player list
cosmeticparticles.enabledParticle trail around the player on rankup
storagetypeyaml (default) or mysql
storagemysql.*Host, port, database, username, password, pool-size
performancemodes.*-tps-thresholdTPS thresholds for HIGH / MEDIUM / LOW cosmetic modes
crossplaybedrock-prefixFloodgate prefix to strip from Bedrock player names
rest-apienabledEnable the optional embedded HTTP API
debug(boolean)Enable verbose debug logging

ranks.yml

Defines every rank. Each top-level key under ranks: is a rank ID.

default-rank: Guest   # Rank assigned to new / unknown players

ranks:
  RankId:
    display-name: "&aDisplay Name"
    next-rank: "NextRankId"       # Empty string = final rank
    slot: 11                      # GUI inventory slot (0โ€“53)
    material: GREEN_WOOL          # Bukkit Material name
    lore:
      - "&7Description line"
    chat-prefix: "&a[Tag]"
    permissions:
      - "some.permission.node"
    commands:
      - "lp user %player% group set rankid"
    requirements:
      money: 1000
      xp-level: 10
      playtime: 1hr               # Human-readable duration format (see Requirements Guide)
      mob-kills: 50
      block-breaks: 500
      permission: "some.required.node"
      statistic-id: "FISH_CAUGHT"
      statistic-value: 10
      quests:
        - "quest_id"
      worlds:
        - "world"
      items:
        DIAMOND: 5

Language files (lang/en.yml, lang/fil.yml, lang/id.yml, lang/es.yml)

Located in plugins/RankForge/lang/. Each file contains:

  • prefix: โ€” the [RankForge] prefix shown before messages
  • messages: โ€” every translatable message string

To add a language, copy en.yml to a new file (e.g., de.yml), translate the messages block, and run /rank reload. Players switch languages with /rank lang set de.

gui.yml

Controls all GUI titles, border materials, slot positions, icons, and themes. Every GUI in RankForge is configurable here without touching any Java code. Apply changes with /rank reload.

YAML storage

Default. Player data is stored in plugins/RankForge/data/playerdata.yml and synced every sync.interval-ticks (default: 200 ticks = 10 seconds). A final flush always runs on clean shutdown.

MySQL storage

storage:
  type: mysql
  mysql:
    host: "localhost"
    port: 3306
    database: "rankforge"
    username: "rankforge_user"
    password: "your_password"
    pool-size: 10

Tables are created automatically. HikariCP handles connection pooling. If the connection fails at startup, RankForge falls back to YAML automatically.


๐Ÿ… Rank Creation Guide

Creating a rank

Add a new key under ranks: in ranks.yml:

ranks:
  Builder:
    display-name: "&e[Builder]"
    next-rank: "Veteran"
    slot: 13
    material: BRICKS
    lore:
      - "&7A creative builder."
    chat-prefix: "&e[Builder]"

Reload with /rank reload. You can also create ranks in-game with /rank create <id>.

Linking rank chains

Each rank points to the next via next-rank. Leave it empty for the final rank:

Guest โ†’ Member โ†’ Veteran โ†’ Elite โ†’ (empty, final rank)

Configuring rewards

ranks:
  Member:
    permissions:
      - "essentials.sethome.multiple.2"   # Applied when player holds this rank
    commands:
      - "lp user %player% group set member"   # Runs on rankup
      - "eco take %player% 1000"

Configuring permissions

  • permissions: โ€” nodes granted while the player holds this rank (managed by LuckPerms or Bukkit attachment)
  • commands: โ€” console commands executed at the moment of rankup (%player% is replaced with the player's name)

Configuring requirements

See the Requirements Guide below for all supported types and the new playtime format.


๐Ÿ“‹ Requirements Guide

All requirements are defined inside a requirements: block within each rank entry.

KeyTypeDescription
moneyDoubleVault balance required. 0 = no requirement.
xp-levelIntegerVanilla Minecraft XP level.
permissionStringA single permission node the player must have.
playtimeStringReal wall-clock playtime (see format below).
mob-killsIntegerTotal mob kills via MOB_KILLS statistic.
block-breaksIntegerBlock breaks tracked by RankForge's counter.
statistic-idStringAny untyped Bukkit Statistic enum name.
statistic-valueIntegerRequired value for statistic-id.
questsList\<String\>Quest IDs checked as rankforge.quest.completed.<id>.
worldsList\<String\>Player must be in one of these world names.
itemsMapMATERIAL_NAME: amount pairs. Items must be in inventory.

Playtime Requirement Format

The playtime key uses a single human-readable string. This is the recommended format.

Supported units:

UnitMeaning
dDays (1d = 1440 minutes)
hrHours (1hr = 60 minutes)
mMinutes
sSeconds (truncated to whole minutes; < 60s = 0)

Units are case-insensitive (D, HR, M, S all work). Extra whitespace is ignored. Any combination of units is accepted.

Examples:

requirements:
  playtime: 30m           # 30 minutes

requirements:
  playtime: 2hr           # 2 hours (120 minutes)

requirements:
  playtime: 7d            # 7 days (10,080 minutes)

requirements:
  playtime: 1d 12hr       # 1 day and 12 hours (2,160 minutes)

requirements:
  playtime: 5d 5hr 5m 5s  # 5 days, 5 hours, 5 minutes (seconds truncated)

requirements:
  playtime: 45s           # 45 seconds โ†’ 0 whole minutes (no requirement in effect)

Backward compatibility:

Existing configurations using playtime continue to work without any changes:

requirements:
  playtime: 60    # Still fully supported โ€” equals "1hr"

The loader checks for playtime first; if absent, it falls back to playtime. No edits to existing ranks.yml files are required.

Full example rank using the duration format:

ranks:
  Veteran:
    display-name: "&2[Veteran]"
    next-rank: "Elite"
    slot: 15
    material: EMERALD
    chat-prefix: "&2[Veteran]"
    commands:
      - "lp user %player% group set veteran"
    requirements:
      money: 10000
      xp-level: 30
      playtime: 10hr
      mob-kills: 100
      block-breaks: 5000
      items:
        DIAMOND: 10

โŒจ๏ธ Commands Guide

Player Commands

CommandPermissionDescription
/rankrankforge.rank.useOpen the animated rank tree GUI
/rank uprankforge.rank.upAttempt to rank up to the next rank
/rank progressrankforge.rank.progressShow a progress bar and requirement breakdown
/rank nextrankforge.rank.nextShow your next rank's display name
/rank currentrankforge.rank.currentShow your current rank
/rank requirementsrankforge.rank.requirementsList unmet requirements for the next rank
/rank historyrankforge.rank.historyView your last 10 rank changes
/rank xprankforge.rank.useView your custom RankForge XP
/rank lang set <lang>rankforge.rank.langSet your preferred language
/rank lang listrankforge.rank.langList all available languages
/rank lang resetrankforge.rank.langReset to the server default language
/rank versionrankforge.rank.system.versionShow plugin and system information
/rank help(none)Show the help screen

Admin Commands

CommandPermissionDescription
/rank editorrankforge.rank.editorOpen the admin rank editor GUI
/rank editor <rankId>rankforge.rank.editorOpen the editor for a specific rank
/rank editor dragrankforge.rank.editor.dragOpen the drag-and-drop slot editor
/rank create <id>rankforge.rank.createCreate a new rank with a specific ID
/rank delete <id>rankforge.rank.deleteDelete a rank (prompts for confirmation)
/rank set <player> <rank>rankforge.rank.setSet a player's rank (online or offline)
/rank force <player> <rank>rankforge.rank.forceForce-set a rank bypassing all checks
/rank bypassreq <player> <requirement>rankforge.rank.bypassreqWaive a single requirement for a player
/rank reset <player>rankforge.rank.resetReset a player to the default rank
/rank reloadrankforge.rank.reloadHot-reload all configuration files
/rank playerlistrankforge.rank.playerlistBrowse all player rank data in a GUI
/rank xp set <player> <amount>rankforge.rank.xp.setSet a player's custom XP
/rank xp add <player> <amount>rankforge.rank.xp.addAdd custom XP to a player
/rank securityrankforge.rank.securityView the admin rollback audit log
/rank history <player>rankforge.rank.adminView another player's rank history

๐Ÿ”‘ Permissions Guide

Player Permissions

PermissionDefaultDescription
rankforge.use.*trueGrants all player permissions (wildcard)
rankforge.usetrueOpen the rank GUI (/rank)
rankforge.use.uptrueRank up (/rank up)
rankforge.use.currenttrueView current rank (/rank current)
rankforge.use.nexttrueView next rank info (/rank next)
rankforge.use.progresstrueView rank progress bar (/rank progress)
rankforge.use.requirementstrueView rank requirements (/rank requirements)
rankforge.use.historytrueView rank history (/rank history)
rankforge.use.helptrueView command help (/rank help)
rankforge.use.langtrueChange language (/rank lang)
rankforge.use.versiontrueView plugin version info (/rank version)
rankforge.use.xptrueView personal XP info (/rank xp)

Administrator Permissions

PermissionDefaultDescription
rankforge.admin.*opGrants all admin permissions (wildcard)
rankforge.admin.reloadopFull plugin reload (/rank reload)
rankforge.admin.editoropOpen the admin rank editor (/rank editor)
rankforge.admin.playerlistopView and edit all player data (/rank playerlist)
rankforge.admin.createopCreate a new rank (/rank create)
rankforge.admin.deleteopDelete a rank (/rank delete)
rankforge.admin.setopSet a player's rank (/rank set)
rankforge.admin.forceopForce-set a rank bypassing requirements (/rank force)
rankforge.admin.resetopReset a player's rank (/rank reset)
rankforge.admin.bypassreqopInstantly complete a requirement for a player (/rank bypassreq)
rankforge.admin.statsopView system statistics (/rank stats)
rankforge.admin.debugopView rank debug info (/rank debug)
rankforge.admin.securityopView anti-bypass status (/rank security)
rankforge.admin.soundopManage sound settings (/rank sound)
rankforge.admin.xpopSet or add XP for other players

Wildcard Permissions

PermissionDefaultDescription
rankforge.*opGrants all RankForge permissions
rankforge.use.*trueGrants all player command permissions
rankforge.admin.*opGrants all administrator command permissions

Quest Permission

PermissionDescription
rankforge.quest.completed.<id>Marks a quest as complete for requirement checks

๐Ÿ“Š PlaceholderAPI Guide

With PlaceholderAPI installed, all %rankforge_*% placeholders are available in any PAPI-compatible plugin (scoreboards, chat formatters, holograms, tab lists, etc.).

PlaceholderExample OutputDescription
%rankforge_rank%VeteranCurrent rank ID
%rankforge_rank_name%&2[Veteran]Current rank display name
%rankforge_rank_display%&2[Veteran]Alias for rank_name
%rankforge_rank_prefix%&2[Veteran]Current rank's chat-prefix
%rankforge_rank_position%3Position in the rank chain (1-based)
%rankforge_is_max_rank%falsetrue if player is at the final rank
%rankforge_next_rank%EliteNext rank ID, or MAX
%rankforge_next_cost%$100,000Next rank's money requirement
%rankforge_cost%$10,000Current rank's money requirement
%rankforge_progress%62.5Overall requirement progress (decimal)
%rankforge_progress_percent%62.5%Same with % appended
%rankforge_progress_bar%โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–‘โ–‘โ–‘โ–‘Visual ASCII progress bar
%rankforge_required_progress%$100,000 Lv75All requirements for the next rank
%rankforge_remaining_progress%$37,500 Lv12What remains unmet
%rankforge_money%$62,500Player's current Vault balance
%rankforge_has_money%falsetrue if player can afford the next rank
%rankforge_missing_money%$37,500Money still needed
%rankforge_requirements_status%ยงcโœ˜ Requirements UnmetMet / unmet status label
%rankforge_requirements_detail%(multiline)Full requirement breakdown
%rankforge_xp_level%30Player's current Minecraft XP level
%rankforge_xp_progress%100%Fraction to next XP level
%rankforge_player%StevePlayer's display name (Bedrock-safe)
%rankforge_uuid%xxxxxxxx-...Player's UUID
%rankforge_lang%enPlayer's active language code
%rankforge_version%3.8Plugin version

โ“ FAQ / Troubleshooting

Rank not updating after /rank up Run /rank progress to see which requirements are unmet. Confirm next-rank is set correctly on the current rank.

PlaceholderAPI not working Ensure PlaceholderAPI is installed and loaded before RankForge. Run /papi list to confirm rankforge is registered. Use /rank reload after installing PAPI.

Vault not detected Vault must be installed and an economy provider (e.g., EssentialsX) must also be present. Check startup log for [SoftDep] Vault=โœ“.

LuckPerms integration not applying permissions LuckPerms must load before RankForge. Verify with /rank version that the plugin loaded successfully. Check that permission nodes in ranks.yml have no spaces or typos.

MySQL connection problems Verify credentials in config.yml. Ensure the database user has CREATE, ALTER, and INSERT privileges. Check console for [DB] Failed to create MySQL tables and the specific SQL error. RankForge automatically falls back to YAML if MySQL is unreachable.

Playtime requirement not progressing Check that PlaytimeTracker initialized on startup (look for errors in the console). Relog โ€” the PlayerJoinEvent re-registers your session start. Confirm the rank's playtime value is greater than zero. Use /rank requirements to see the playtime line.

Old playtime config stopped working It has not stopped working. The key is fully supported. Add playtime: 1hr to new ranks going forward; existing playtime entries require no changes.

Invalid playtime format error Ensure the value uses only the supported units (d, hr, m, s) with whole numbers and no special characters. Valid: 1d 12hr 30m. Invalid: 1.5d, 2hours, 90.

Configuration mistakes Use a YAML validator (e.g., yaml-online-parser.appspot.com) to check ranks.yml for syntax errors. All invalid ranks are logged and skipped โ€” look for [YamlLoader] Skipped rank warnings in the console.


๐Ÿ’ก Best Practices

Organizing rank chains

  • Keep rank IDs simple and consistent (Guest, Member, Veteran) โ€” they are stored in player data.
  • Always set next-rank for every non-final rank to avoid silent dead-ends.
  • Use the slot field to arrange ranks visually in the GUI from left to right.

Optimizing performance

  • Use YAML storage for single servers; MySQL for networks with many concurrent players.
  • Keep sync.interval-ticks at 200 (10 seconds) or higher to reduce disk I/O.
  • Disable cosmetics you don't use (particles, bossbar) to reduce per-player overhead on busy servers.
  • The TPS-aware performance system automatically suppresses heavy effects when the server is under load.

Creating balanced progression

  • Start playtime requirements low (30mโ€“1hr for the first rank) and increase gradually.
  • Combine playtime with activity-based requirements (block-breaks, mob-kills) so idle AFK players don't auto-rank.
  • Test all requirements on yourself with /rank set <yourself> <rank> and /rank progress before opening to players.

Maintaining configuration files

  • Always use /rank reload โ€” never /reload.
  • Back up ranks.yml and playerdata.yml (or your MySQL database) before making major changes.
  • When renaming a rank ID, update default-rank and all next-rank references, then use /rank reload. Players with the old ID are automatically repaired to default-rank.
  • Use the in-game admin editor (/rank editor) for safe edits that automatically validate and save the file.

Made with โค๏ธ by JoshuaOP

โญ If RankForge helps your server, please star the repository โ€” it helps others find the project!

GitHub Stars GitHub Forks