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.
setItems() on KitGiveEvent) so you can change behaviour without reimplementing it.
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() | String | Internal kit id, e.g. starter. |
| String getDisplayName() | String | Human-readable name shown in GUIs. |
| String getRequiredPermission() | String | Permission needed to use this kit, or empty. |
| long getCooldownInSeconds() | long | Cooldown between claims in seconds. |
| boolean isOneTimeUse() | boolean | True if the kit can only ever be claimed once. |
| boolean isGrantedOnFirstJoin() | boolean | True if new players get this kit automatically on their first join. |
| int getMaximumClaimsAllowed() | int | Max total claims, or -1 if unlimited. |
| List<ItemStack> getItemStacks() | List<ItemStack> | The items handed out on claim. |
| String getKitDescription() | String | Optional description for the kit GUI. |
| boolean isSynchronizedAcrossNetwork() | boolean | Whether claims sync across the network (MySQL expansion). |
| int getGuiSlot() | int | Slot the kit occupies in the kits GUI. |
| int getGuiPage() | int | GUI page the kit appears on. |
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
A player's claim history for one kit. This is what powers cooldowns and one-time checks.
| Method | Returns | Description |
|---|---|---|
| UUID getPlayerId() | UUID | The claiming player. |
| String getKitName() | String | The kit this profile belongs to. |
| long getLastClaimedTimestamp() | long | Millis timestamp of the most recent claim, or 0. |
| int getTotalClaimCount() | int | Lifetime number of claims for this kit. |
| boolean hasEverClaimed() | boolean | Whether the player has claimed this kit at least once. |
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
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) | Kit | Looks 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) | boolean | True if the player can claim again right now. |
| CompletableFuture<Long> fetchCooldownRemainingAsync(Player player, Kit kit) | long | Seconds remaining, fetched from storage. |
| long getRemainingCooldownSeconds(Player player, Kit kit) | long | Seconds remaining, from the in-memory cache. |
| boolean hasPlayerClaimed(Player player, Kit kit) | boolean | Whether the player has ever claimed this kit. |
| int getPlayerClaimCount(Player player, Kit kit) | int | Total claims by the player for this kit. |
| KitClaimProfile fetchClaimProfile(Player player, Kit kit) | KitClaimProfile | The claim profile for a (player, kit) pair. |
| boolean isClaimAllowedFor(Player player, Kit kit) | boolean | Cooldown + one-time + max-claims + availability gate. |
| boolean isPermittedToUse(Player player, Kit kit) | boolean | Permission check only, via the permission event. |
| void reloadKitDefinitions() | void | Reloads kit config; cached claim data is preserved. |
| CompletableFuture<Void> claimKitForPlayer(Player player, Kit kit) | Void | Runs the full claim flow (events + item give + persistence). |
| int getTotalLoadedKitCount() | int | Number of loaded kits. |
| boolean isKitLoaded(String name) | boolean | Whether 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:
Permission check
KitPermissionCheckEvent (cancellable). You can grant or deny access here.
Availability check
KitAvailableCheckEvent (cancellable). Cooldown, one-time, and claim limits are validated; you can override the result.
Claim intent
KitClaimEvent (cancellable). The final veto point before anything is granted.
Item give
KitGiveEvent (cancellable). Inspect or replace the ItemStacks before they reach the player.
Persistence
KitDataSaveEvent fires with the new claim timestamp/count, then KitPostClaimEvent announces the completed claim.
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
@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.
@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
@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.
@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.
@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
@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
// 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
// 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
@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
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
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));
}