EssentialsC API / Kits API

Kits API

Kits, claim profiles, cooldowns, and the complete claim flow. Package net.godlycow.org.essc.api.kit.

Overview

The kits module reads kit definitions, tracks a player's claim history, runs the full claim flow from your own code, and fires 11 events covering permission checks, availability, cooldowns, item giving, and storage.

The kit module is the most event-driven part of the API. Most events are cancellable, and several expose mutable results (like setItems() on KitGiveEvent) so you can change behaviour without reimplementing it.

Kit

interface net.godlycow.org.essc.api.kit.Kit

Immutable snapshot of a kit as configured by the server. Read it like a config file; you never build one yourself.

Method Returns Description
String getName()StringInternal kit id, e.g. starter.
String getDisplayName()StringHuman-readable name shown in GUIs.
String getRequiredPermission()StringPermission needed to use this kit, or empty.
long getCooldownInSeconds()longCooldown between claims in seconds.
boolean isOneTimeUse()booleanTrue if the kit can only ever be claimed once.
boolean isGrantedOnFirstJoin()booleanTrue if new players get this kit automatically on their first join.
int getMaximumClaimsAllowed()intMax total claims, or -1 if unlimited.
List<ItemStack> getItemStacks()List<ItemStack>The items handed out on claim.
String getKitDescription()StringOptional description for the kit GUI.
boolean isSynchronizedAcrossNetwork()booleanWhether claims sync across the network (MySQL expansion).
int getGuiSlot()intSlot the kit occupies in the kits GUI.
int getGuiPage()intGUI page the kit appears on.
InspectKit.java
Kit kit = kits.findKitByName("vip");
if (kit == null) return;

// Expose kit info to your own GUI.
int cooldown  = (int) kit.getCooldownInSeconds();
int maxClaims = kit.getMaximumClaimsAllowed();
boolean oneTime = kit.isOneTimeUse();

// Copy the item list (getItemStacks() returns a fresh list).
List<ItemStack> items = new ArrayList<>(kit.getItemStacks());

KitClaimProfile

interface net.godlycow.org.essc.api.kit.KitClaimProfile

A player's claim history for one kit. This is what powers cooldowns and one-time checks.

Method Returns Description
UUID getPlayerId()UUIDThe claiming player.
String getKitName()StringThe kit this profile belongs to.
long getLastClaimedTimestamp()longMillis timestamp of the most recent claim, or 0.
int getTotalClaimCount()intLifetime number of claims for this kit.
boolean hasEverClaimed()booleanWhether the player has claimed this kit at least once.
ClaimProfileExample.java
KitClaimProfile profile = kits.fetchClaimProfile(player, kit);

long secondsSinceLastClaim =
    (System.currentTimeMillis() - profile.getLastClaimedTimestamp()) / 1000;

if (profile.getTotalClaimCount() >= 3) {
    player.sendMessage("You've claimed this kit 3 times already.");
}

KitManager

interface net.godlycow.org.essc.api.kit.KitManager

Get it via api.getKitManager(). Queries are mostly synchronous (claim data is cached in the plugin); the async methods hit storage.

Method Returns Description
Collection<Kit> getLoadedKits()Collection<Kit>All kits loaded from config.
Kit findKitByName(String name)KitLooks up a kit by id, or null.
Collection<Kit> getKitsAvailableTo(Player player)Collection<Kit>Kits the player may use (permission + availability checks).
boolean hasCooldownExpiredFor(Player player, Kit kit)booleanTrue if the player can claim again right now.
CompletableFuture<Long> fetchCooldownRemainingAsync(Player player, Kit kit)longSeconds remaining, fetched from storage.
long getRemainingCooldownSeconds(Player player, Kit kit)longSeconds remaining, from the in-memory cache.
boolean hasPlayerClaimed(Player player, Kit kit)booleanWhether the player has ever claimed this kit.
int getPlayerClaimCount(Player player, Kit kit)intTotal claims by the player for this kit.
KitClaimProfile fetchClaimProfile(Player player, Kit kit)KitClaimProfileThe claim profile for a (player, kit) pair.
boolean isClaimAllowedFor(Player player, Kit kit)booleanCooldown + one-time + max-claims + availability gate.
boolean isPermittedToUse(Player player, Kit kit)booleanPermission check only, via the permission event.
void reloadKitDefinitions()voidReloads kit config; cached claim data is preserved.
CompletableFuture<Void> claimKitForPlayer(Player player, Kit kit)VoidRuns the full claim flow (events + item give + persistence).
int getTotalLoadedKitCount()intNumber of loaded kits.
boolean isKitLoaded(String name)booleanWhether a kit id is currently loaded.

The claim flow

claimKitForPlayer(player, kit) runs the whole pipeline. Know the order so your listeners fire where you expect:

1

Permission check

KitPermissionCheckEvent (cancellable). You can grant or deny access here.

2

Availability check

KitAvailableCheckEvent (cancellable). Cooldown, one-time, and claim limits are validated; you can override the result.

3

Claim intent

KitClaimEvent (cancellable). The final veto point before anything is granted.

4

Item give

KitGiveEvent (cancellable). Inspect or replace the ItemStacks before they reach the player.

5

Persistence

KitDataSaveEvent fires with the new claim timestamp/count, then KitPostClaimEvent announces the completed claim.

Use claimKitForPlayer() when you want EssentialsC to handle everything - items, storage, the lot. If you just want to hand items out without recording a claim, cancelling KitClaimEvent won't do it - read kit.getItemStacks() and give them yourself.

Events

All eleven kit events live in net.godlycow.org.essc.api.kit.event.

KitPermissionCheckEvent - cancellable

KitPermissionListener.java
@EventHandler
public void onKitPermissionCheck(KitPermissionCheckEvent event) {
    // Let anyone use the "starter" kit regardless of permissions.
    if (event.getKit().getName().equals("starter")) {
        event.setHasPermission(true);
    }
}

KitAvailableCheckEvent - cancellable

Note: the flag is named available with a denialReason. Cancelling the event also blocks the claim.

KitAvailableListener.java
@EventHandler
public void onKitAvailableCheck(KitAvailableCheckEvent event) {
    // Force "vip" to be unavailable during maintenance.
    if (maintenance && event.getKit().getName().equals("vip")) {
        event.setAvailable(false);
        event.setDenialReason("Kit temporarily disabled.");
    }
}

KitClaimEvent - cancellable

KitClaimListener.java
@EventHandler
public void onKitClaim(KitClaimEvent event) {
    // Block claims while the player is in a "no-kit" world.
    if (event.getPlayer().getWorld().getName().equals("pvp_arena")) {
        event.setCancelled(true);
        return;
    }
    // Announce the claim.
    server.broadcast(event.getPlayer().getName() + " claimed " + event.getKit().getDisplayName());
}

KitGiveEvent - cancellable

The ItemStack list is a mutable copy, so add, remove, or replace items before they reach the player.

KitGiveListener.java
@EventHandler
public void onKitGive(KitGiveEvent event) {
    List<ItemStack> items = new ArrayList<>(event.getItems());

    // Add a loyalty bonus on top of the configured items.
    items.add(new ItemStack(Material.GOLD_INGOT, 8));
    event.setItems(items);

    // Or strip a banned item entirely.
    items.removeIf(s -> s.getType() == Material.BEDROCK);
    event.setItems(items);
}

KitFirstJoinEvent - cancellable

Fired when a first-join kit is about to be granted to a new player.

KitFirstJoinListener.java
@EventHandler
public void onKitFirstJoin(KitFirstJoinEvent event) {
    // Skip the starter kit for players joining from a whitelisted network.
    if (event.getPlayer().hasPermission("network.started")) {
        event.setCancelled(true);
    }
}

KitCooldownExpireEvent

KitCooldownListener.java
@EventHandler
public void onKitCooldownExpire(KitCooldownExpireEvent event) {
    // Notify the player their kit is ready again.
    event.getPlayer().sendMessage("Your " + event.getKit().getName() + " kit is ready!");
}

KitLoadEvent / KitReloadEvent

KitLoadListener.java
// Fired once per kit as kit config is loaded.
@EventHandler
public void onKitLoad(KitLoadEvent event) {
    getLogger().info("Loaded kit " + event.getKit().getName()
        + " from " + event.getSourceFileName());
}

// Fired after a full kit reload.
@EventHandler
public void onKitReload(KitReloadEvent event) {
    getLogger().info("Kit reload complete - " + event.getKitCount() + " kits.");
}

KitDataLoadEvent / KitDataSaveEvent

KitDataListener.java
// A player's claim entries were loaded from storage.
@EventHandler
public void onKitDataLoad(KitDataLoadEvent event) {
    getLogger().info("Loaded " + event.getLoadedEntryCount()
        + " claim entries for " + event.getPlayerName());
}

// A claim was persisted.
@EventHandler
public void onKitDataSave(KitDataSaveEvent event) {
    getLogger().info("Saved claim #" + event.getNewClaimCount()
        + " for kit " + event.getKit().getName());
}

// A claim completed (after persistence).
@EventHandler
public void onKitPostClaim(KitPostClaimEvent event) {
    long timestamp = event.getClaimTimestamp();
    event.getPlayer().sendMessage("Enjoy your " + event.getKit().getDisplayName() + "!");
}

Worked examples

Run the claim flow from your own command

KitCommand.java
@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
    if (!(sender instanceof Player p) || args.length == 0) return true;

    KitManager kits = api.getKitManager();
    Kit kit = kits.findKitByName(args[0]);
    if (kit == null) {
        p.sendMessage("Unknown kit: " + args[0]);
        return true;
    }

    // Respect the plugin's own rules, but let the events do the vetoing.
    if (!kits.isPermittedToUse(p, kit)) {
        p.sendMessage("You don't have permission for that kit.");
        return true;
    }
    if (!kits.isClaimAllowedFor(p, kit)) {
        long remaining = kits.getRemainingCooldownSeconds(p, kit);
        p.sendMessage("Kit on cooldown - " + remaining + "s left.");
        return true;
    }

    // Fire the full pipeline (events can still cancel it).
    kits.claimKitForPlayer(p, kit).exceptionally(ex -> {
        p.sendMessage("Something went wrong claiming that kit.");
        return null;
    });
    return true;
}

Show kit availability in a menu

KitMenu.java
KitManager kits = api.getKitManager();

for (Kit kit : kits.getKitsAvailableTo(player)) {
    long cd = kits.getRemainingCooldownSeconds(player, kit);
    String status = cd > 0
        ? "on cooldown (" + cd + "s)"
        : "claimable";
    player.sendMessage(kit.getDisplayName() + " - " + status);
}

Grant a kit without recording it

LooseGive.java
Kit kit = kits.findKitByName("party");
if (kit == null) return;

// Hand items straight over - no claim recorded, no cooldown applied.
for (ItemStack item : kit.getItemStacks()) {
    Map<Integer, ItemStack> leftover = player.getInventory().addItem(item);
    leftover.values().forEach(drop -> player.getWorld().dropItemNaturally(player.getLocation(), drop));
}