Skip to content
Plugin API

Plugin API

Overview

SCS2 ships a public Java API for other plugins to integrate with the claim system — read claim data, listen to events, drive admin actions, and (since 2.5.0) declare custom flags and role-permissions.

The API is published as a separate artifact SimpleClaimSystem-API via JitPack. Add it as a provided/compileOnly dependency in your build file:

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

<dependency>
    <groupId>com.github.Xyness</groupId>
    <artifactId>SimpleClaimSystem-API</artifactId>
    <version>v2.5.10</version>
    <scope>provided</scope>
</dependency>

Gradle (Groovy): compileOnly 'com.github.Xyness:SimpleClaimSystem-API:v2.5.10' with the JitPack repo maven { url 'https://jitpack.io' }.

Declare SimpleClaimSystem in your plugin.yml so it loads first:

depend: [SimpleClaimSystem]   # or softdepend: [SimpleClaimSystem]

This page documents the whole API surface. The authoritative reference is the JitPack-generated Javadoc; the source lives in the SimpleClaimSystem-API repository.

Getting the API instance

Fetch the API once SCS2 is enabled. Always guard with isRegistered() so your plugin still loads when SCS2 is absent:

import fr.xyness.SimpleClaimSystem.API.SCS_API;
import fr.xyness.SimpleClaimSystem.API.SCS_API_Provider;

if (SCS_API_Provider.isRegistered()) {
    SCS_API api = SCS_API_Provider.get();
    // ... use the API
}

Every example below is called on that api instance. Types live under fr.xyness.SimpleClaimSystem.Types (Claim, PlayerData, ChunkKey) and ...Enums (ClaimRole, WorldMode).

Reading claims & players

From a chunk or location

Use the synchronous getters on hot paths inside listeners (the chunk is loaded and the claim is almost certainly cached). Use the async ones from commands, GUIs or scheduled tasks, where a cold chunk could otherwise hit the database on the calling thread.

Optional<Claim> claim = api.getClaim(player.getLocation().getChunk());
claim.ifPresent(c -> {
    String owner = c.getOwnerName();
    String name  = c.getClaimName();
});

// Async — preferred outside listeners
api.getClaimAsync(chunk).thenAccept(opt -> opt.ifPresent(c -> { /* ... */ }));

// Batch several chunks at once
Map<ChunkKey, Optional<Claim>> claims = api.getClaims(keys);

Quick checks (no Claim object needed)

boolean claimed  = api.isClaimed(player.getLocation());   // ChunkKey / Chunk / Location
boolean canBuild = api.hasPermission(chunk, playerId, "place_block");
boolean banned   = api.isBanned(chunk, playerId);
boolean member   = api.isMember(chunk, playerId);
String  role     = api.getRole(chunk, playerId);          // "VISITOR" if not a member
Boolean pvp      = api.getFlag(chunk, "pvp");

Players & world mode

Optional<PlayerData> data = api.getPlayer(player.getUniqueId());
data.ifPresent(pd -> { String name = pd.getName(); });
// Async: getPlayerAsync, getPlayerByNameAsync, getPlayersAsync, getPlayerNamesAsync

WorldMode mode = api.getWorldMode(world);   // SURVIVAL, SURVIVAL_REQUIRING_CLAIMS, PROTECTED, DISABLED

Roles & permissions

Roles are plain Strings. The four built-ins are VISITOR, MEMBER, MODERATOR and OWNER; claim owners can also create custom roles. Permissions and flags resolve the same way for both.

String  role      = claim.getRole(playerId);          // built-in or custom, "VISITOR" if none
boolean canBuild  = claim.getPermission(role, "place_block");
boolean isDefault = ClaimRole.isDefault(role);        // true for VISITOR/MEMBER/MODERATOR/OWNER

List<String> all    = claim.getAllRoles();            // defaults + custom
List<String> custom = claim.getCustomRoles();

boolean explosions = claim.getFlag("creeper_explosions");

Enforce a permission in your own listener — owners are always allowed, and honour the staff bypass node:

String role = claim.getRole(player.getUniqueId());
if (!claim.getPermission(role, "my_perm")
        && !player.hasPermission("scs.bypass.my_perm")) {
    event.setCancelled(true);
}

Modifying claims

Two layers. Claim helpers mutate the in-memory object only — no database write, no events — handy while assembling a claim. SCS_API methods persist to the database, refresh caches and fire the matching events; most return a CompletableFuture.

// ❌ Maps from getMembers() / getFlags() / getPermissions() are unmodifiable
claim.getMembers().put(uuid, "MEMBER");           // throws UnsupportedOperationException

// ✅ In-memory only
claim.addMember(uuid, "MEMBER");
claim.setFlag("pvp", false);
claim.setPermission("MEMBER", "place_block", true);

// ✅ Persist + caches + events
api.addMember(claim, uuid, "MEMBER");
api.setMemberRole(claim, uuid, "MODERATOR");
api.removeMember(claim, uuid);
api.banPlayer(claim, uuid, LocalDateTime.now().plusDays(7));
api.unbanPlayer(claim, uuid);
api.setFlag(claim, "pvp", false);
api.setPermission(claim, "MEMBER", "place_block", true);

Bulk member ops (Factions / Kingdoms style)

api.addMemberToAllClaims(leaderUuid, newMemberUuid, "MEMBER");
api.removeMemberFromAllClaims(leaderUuid, leavingMemberUuid);

Creating & deleting claims (2.7.1)

The lifecycle methods apply the configured defaults, fire the matching events and write every table in one transaction. Player limits, world rules and economy are not checked — your plugin decides who may create what.

api.createClaim(ownerUuid, ownerName, "shop-%n", chunk)      // %n = lowest free number
   .thenAccept(opt -> opt.ifPresent(claim -> {
       api.setSpawnLocation(claim, spawn);
       api.setDescription(claim, "Server shop");
   }));

api.addChunk(claim, chunk);       // false if already claimed or vetoed
api.removeChunk(claim, chunk);    // removing the last chunk deletes the claim
api.deleteClaim(claim);
api.setClaimName(claim, "market");
api.createRole(claim, "TRADER");  // seeded from the claim's MEMBER permissions
api.deleteRole(claim, "TRADER");  // members holding it fall back to MEMBER

Warps & economy (2.7.1)

boolean open  = api.isWarpOpen(claim);
double  price = api.getVisitPrice(claim);
api.setWarp(claim, true);                 // fires ClaimWarpToggleEvent
api.setVisitPrice(claim, 250.0);
Set<UUID> owners = api.getOpenWarpOwners();

boolean sale  = api.isForSale(claim);
double  asked = api.getSalePrice(claim);
api.setForSale(claim, true, 10000.0);     // fires ClaimSaleEvent

Player limits & stats

int    maxClaims  = api.getMaxClaims(player);
int    maxChunks  = api.getMaxChunks(player);
int    maxRadius  = api.getMaxRadius(player);
int    maxMembers = api.getMaxMembers(player);
double cost       = api.getChunkCost(player);
double multiplier = api.getCostMultiplier(player);

int claims = api.getClaimCount(playerId);   // current totals
int chunks = api.getChunkCount(playerId);

// 2.7.1
int  perClaim = api.getMaxChunksPerClaim(player);
int  maxRoles = api.getMaxRoles(player);
int  delay    = api.getTeleportDelay(player);
int  distance = api.getMinDistance(player);
long flyTime  = api.getFlyTime(playerId);   // remaining claim-fly seconds

Querying claims by owner

List<Claim>  claims = api.getClaimsByOwner(ownerUuid);     // also getClaimsByOwnerAsync
List<String> names  = api.getClaimNamesByOwner(ownerUuid);
Optional<Claim> one  = api.getClaimByOwnerAndName(ownerUuid, "My Base");

Map<UUID, String>        members = api.getClaimMembers(ownerUuid, "My Base");
Map<UUID, LocalDateTime> banned  = api.getClaimBanned(ownerUuid, "My Base");

Favourites

boolean added   = api.addFavorite(playerUuid, claim);
boolean removed = api.removeFavorite(playerUuid, claim);
boolean fav     = api.isFavorite(playerUuid, claim.getId());

List<Integer> ids  = api.getFavoriteClaimIds(playerUuid);
List<Claim>   live = api.getFavoriteClaims(playerUuid);   // ids that no longer resolve are dropped

React to changes with ClaimFavoriteEventgetAction() returns FAVORITE or UNFAVORITE.

Reading plugin settings

Read any resolved config.yml value through the API — useful when your integration needs to respect the same options the plugin uses (economy toggles, default icon, tax settings, ...). Keys are the dot-separated config.yml paths.

Object  raw   = api.getSetting("claims.default.icon");           // null if unset
boolean tax   = api.getBooleanSetting("claims.tax.enabled", false);
String  icon  = api.getStringSetting("claims.default.icon", "FARMLAND");
int     delay = api.getIntSetting("claims.confirmation-delay", 30);
double  visit = api.getDoubleSetting("claims.default.visitPrice", 0.0);

// Permissions and flags applied to unclaimed chunks in the two special world modes:
Map<String, Boolean> protectedPerms = api.getPermissionsForProtectedMode();
Map<String, Boolean> srcPerms       = api.getPermissionsForSurvivalRequiringClaimsMode();
Map<String, Boolean> protectedFlags = api.getFlagsForProtectedMode();
Map<String, Boolean> srcFlags       = api.getFlagsForSurvivalRequiringClaimsMode();

The typed getters return your fallback when the key is absent; getSetting returns the raw Object (or null). The four mode maps are read-only views of the plugin's live settings. They were named getSettingsFor*Mode() before 2.7.1, where they returned null; the flag variants are new.