Official Guide

APIs & history

Explore the complete APIs and history documentation below for RankForge.

๐ŸŒ REST API

RankForge includes an optional lightweight embedded HTTP server for external dashboard and monitoring integrations.

Enabling

rest-api:
  enabled: true
  port: 4567
  token: "my_secret_token"    # Leave empty to disable auth (development only)

Run /rank reload after changing these settings.

Endpoints

All endpoints are GET only. Responses are application/json.

GET /api/status

Plugin status and rank count.

{
  "plugin": "RankForge",
  "version": "3.7",
  "ranks": 5,
  "players": 12
}

GET /api/ranks

Array of all loaded rank definitions.

[
  {
    "id": "Guest",
    "displayName": "&7[Guest]",
    "nextRank": "Member",
    "slot": 11,
    "requiredMoney": 0,
    "requiredXpLevel": 0
  },
  ...
]

GET /api/player/{uuid}

Rank data for a specific player (must be in the active cache).

{
  "uuid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "name": "Steve",
  "rank": "Veteran",
  "experience": 1500,
  "money": 62500.0
}

Authentication

When token is set, every request must include:

Authorization: Bearer my_secret_token

Requests without a valid token receive 401 Unauthorized.

Never expose the REST API port to the public internet. Place it behind a reverse proxy (nginx, Caddy) with TLS, or restrict it to localhost/VPN access only. The embedded server has no TLS support.


๐Ÿ“ˆ Experience & Rank History

Experience Manager

RankForge tracks a custom experience value per player (separate from vanilla Minecraft XP). This can be used in conjunction with external systems.

# Admin commands
/rank xp                          โ† view your own XP
/rank xp set Steve 1000           โ† set Steve's XP to 1000
/rank xp add Steve 250            โ† add 250 XP to Steve

The experience value is stored in the player's data record and accessible via the API:

long xp = plugin.getExperienceManager().getXp(player);
plugin.getExperienceManager().set(player, 500L);
plugin.getExperienceManager().award(player, 100L);

Rank History

Every rank change (rankup, admin set, force, reset) is recorded by RankHistoryManager with a timestamp.

Players can view their own history:

/rank history

Output shows the last 10 entries (older entries are shown as a count). History is stored persistently and loaded asynchronously to avoid blocking the main thread.

Admins can pull up any player's history โ€” online or offline โ€” either with /rank history <player> or by clicking the Rank History button in the Player Data Editor GUI, both of which share the same formatter so the output is always consistent regardless of where it's viewed from.


๐Ÿงฉ Developer API

RankForge exposes a public API at com.joshuaop.rankforge.api.RankForgeAPI.

Adding as a Dependency

Maven:

<repository>
  <id>jitpack.io</id>
  <url>https://jitpack.io</url>
</repository>

<dependency>
  <groupId>com.github.JoshuaOP</groupId>
  <artifactId>RankForge</artifactId>
  <version>3.7</version>
  <scope>provided</scope>
</dependency>

Gradle:

repositories {
    maven { url 'https://jitpack.io' }
}
dependencies {
    compileOnly 'com.github.JoshuaOP:RankForge:3.7'
}

plugin.yml:

softdepend: [RankForge]

Getting the API Instance

import com.joshuaop.rankforge.api.RankForgeAPI;

public class MyPlugin extends JavaPlugin {
    private RankForgeAPI rankForge;

    @Override
    public void onEnable() {
        if (getServer().getPluginManager().getPlugin("RankForge") != null) {
            rankForge = RankForgeAPI.getInstance();
        }
    }
}

Core API Methods

RankForgeAPI api = RankForgeAPI.getInstance();

// โ”€โ”€ Read player data โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
PlayerRank rank = api.getPlayerRank(player);
String rankId   = rank.getRankId();

// โ”€โ”€ Trigger rankup โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
boolean success = api.rankUp(player);

// โ”€โ”€ Set rank โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
api.setRank(player, "Veteran");
api.setRank(player, "Veteran", commandSenderForAudit);

// โ”€โ”€ Reset rank โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
api.resetRank(player);
api.resetRank(player, commandSenderForAudit);

// โ”€โ”€ Progress โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
double progressPercent = api.getProgress(player);    // 0.0โ€“100.0

// โ”€โ”€ Crossplay-safe name โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
String cleanName = api.getCleanName(player);         // Strips Bedrock prefix

// โ”€โ”€ Experience โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
long xp = api.getExperienceManager().getXp(player);
api.getExperienceManager().award(player, 100L);
api.getExperienceManager().set(player, 500L);

// โ”€โ”€ History โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
List<RankHistoryEntry> history = api.getHistoryManager().getHistory(uuid);

Listening to RankForge Events

All events are in com.joshuaop.rankforge.api.event.

RankupEvent (Cancellable)

Fired when a player is about to rank up via /rank up or the API.

@EventHandler
public void onRankup(RankupEvent event) {
    Player player   = event.getPlayer();
    String oldRank  = event.getOldRankId();
    String newRank  = event.getNewRankId();

    // Cancel the rankup
    if (someCondition) {
        event.setCancelled(true);
        player.sendMessage("Rankup blocked!");
        return;
    }

    // Custom logic
    player.sendMessage("Congrats on reaching " + newRank + "!");
}

RankSetEvent

Fired when a rank is set via /rank set or api.setRank().

@EventHandler
public void onRankSet(RankSetEvent event) {
    String newRank = event.getNewRankId();
    // Log or react to admin rank changes
}

RankResetEvent

Fired when a rank is reset via /rank reset or api.resetRank().

@EventHandler
public void onRankReset(RankResetEvent event) {
    Player player = event.getPlayer();
    // React to rank resets
}

Registering a Custom Requirement

import com.joshuaop.rankforge.api.requirement.CustomRequirement;
import com.joshuaop.rankforge.rank.RankModel;
import org.bukkit.entity.Player;

public class QuestsRequirement implements CustomRequirement {

    @Override
    public String getId() {
        return "myplugin:quests_completed";
    }

    @Override
    public boolean check(Player player, RankModel rank, String configValue) {
        int required = Integer.parseInt(configValue);
        int completed = MyQuestPlugin.getCompleted(player);
        return completed >= required;
    }

    @Override
    public String getUnmetMessage(Player player, RankModel rank, String configValue) {
        int required  = Integer.parseInt(configValue);
        int completed = MyQuestPlugin.getCompleted(player);
        return "ยง7Quests: ยงc" + completed + "/" + required;
    }
}

// Register during onEnable โ€” after RankForge is loaded:
RankForgeAPI api = RankForgeAPI.getInstance();
if (api != null) {
    api.getCustomRequirementRegistry().register(new QuestsRequirement());
}

// Then configure per-rank in Java (not YAML):
plugin.getRequirementManager().addRankRequirement("Elite", "myplugin:quests_completed", "10");

Replacing the GUI

import com.joshuaop.rankforge.api.gui.ExternalGUIProvider;

public class MyGUIProvider implements ExternalGUIProvider {

    @Override
    public GuiType getType() {
        return GuiType.RANK_TREE;
    }

    @Override
    public void open(Player player) {
        // Open your custom GUI
        MyCustomGUI.open(player);
    }
}

// Register:
api.getExternalGUIRegistry().register(new MyGUIProvider());

Registering a Plugin Hook

import com.joshuaop.rankforge.api.hook.PluginHook;

public class MyHook implements PluginHook {
    @Override
    public String getId() { return "myplugin"; }

    @Override
    public void onEnable()  { /* hook setup */ }

    @Override
    public void onDisable() { /* hook teardown */ }
}

api.getHookRegistry().register(new MyHook());