Configuration

General Settings

The main configuration file is located at /plugins/SimpleClaimSystem/config.yml. Reload after editing with /scs reload.

# Logger verbosity
logger: NORMAL            # NORMAL | DEBUG

# Language file (from /langs)
lang: "en_US.yml"

# Update checks
update:
  check: true             # poll for new versions on startup
  notifications: true     # notify in-game on join (requires scs.update.notifications)

# Command aliases — add extra command names that invoke the same handler
command-aliases:
  claim: []
  parea: []
  unclaim: []
  claims: []
  scs: []

Key reference

KeyDescription
loggerNORMAL = standard info/warn/error. DEBUG = verbose (cache hits, Redis SETEX, DAO inserts). Only turn on when troubleshooting; produces a lot of console noise.
langFilename of the language file inside /langs. Shipped with en_US.yml and fr_FR.yml. Drop your own file in the folder to add a translation.
update.checkOn startup, the plugin contacts the release feed to detect newer versions.
update.notificationsWhen a newer version is detected, notify players who have scs.update.notifications on join.
command-aliases.*Extra command names mapped to each built-in command. Example: claim: [c, protect] makes /c and /protect behave like /claim.

Database

SCS2 uses SQLite by default but supports MySQL / MariaDB for larger servers and multi-server setups:

database:
  enabled: false         # false = SQLite (local), true = use the MySQL block below
  hostname: localhost
  port: 3306
  name: database_name    # schema (must already exist on the server)
  username: root
  password: pass
  hikari:
    # Connection-leak threshold (ms). Hikari logs a stack trace identifying the borrower
    # if a connection is held longer than this without being returned. Useful to surface
    # accidental synchronous DB calls on hot paths. 0 disables the check.
    leak-detection-ms: 5000

Key reference

KeyDescription
enabledfalse = SQLite at /plugins/SimpleClaimSystem/storage.db. true = connect to MySQL using the fields below. Switch is safe to flip — use the transfer commands to migrate data.
hostname / portMySQL host/port. Defaults to localhost:3306.
nameDatabase (schema) name. Must already exist and the user below must have DDL rights on it (the plugin creates its own tables).
username / passwordCredentials for the account the plugin connects with. Change the default root/pass before deploying.
hikari.leak-detection-msIf a borrowed connection isn't returned within this many milliseconds, Hikari logs a stack trace pointing at the borrower. Catch synchronous DB calls on hot paths quickly. Set 0 to disable.

Database transfer

You can transfer data between local (SQLite) and distant (MySQL) databases at any time:

  • /scs transferLocalToDistant — Copy all SQLite data to MySQL
  • /scs transferDistantToLocal — Copy all MySQL data to SQLite

The connection pool is managed by HikariCP internally. For large servers MySQL is strongly recommended over SQLite — concurrent writes are faster.

Redis (Optional Cache Layer)

Redis is an optional third caching layer between the in-memory cache (Caffeine) and the SQL database. It does not replace MySQL and is not a cross-server synchronization bus — it's purely a performance optimization.

How the cache stack works

Every claim / player read follows this order:

  1. Caffeine (in-memory, per-server) — hit: returned instantly.
  2. Redis (if enabled) — miss in Caffeine ⇒ check Redis. Hit: the value is deserialised and cached in Caffeine. Miss: fall through.
  3. MySQL / SQLite — miss everywhere ⇒ query the database. The result is written to Redis (if enabled) and Caffeine for subsequent reads.

Writes go to the database first, then to Redis, then to Caffeine, and will invalidate both caches if any step fails to avoid stale reads.

redis:
  enabled: false
  hostname: localhost
  port: 6379
  password: ""                  # empty = no auth; set on any internet-facing Redis
  database: 0                   # Redis logical db (0-15 by default)
  command-timeout-seconds: 30   # bump on slow/remote Redis; 0 = no client-side timeout

Key reference

KeyDescription
enabledWhen true, the plugin opens a Redis connection at startup and treats it as cache layer 2. Leaving this off is fine — Caffeine alone handles most workloads.
hostname / portRedis host/port. Defaults are the vanilla Redis install.
passwordOptional AUTH password. Leave empty for unauthenticated Redis (only safe on localhost).
databaseLogical database number. Use distinct numbers if you're sharing one Redis between several plugins.
command-timeout-secondsPer-command timeout for Lettuce. Bump if you see "Command timed out" on joins with many visible claimed chunks, or on a slow/remote Redis. Set to 0 to disable the client-side timeout entirely.

Storage schema

Since v2.2.4 the plugin stores claims under a two-key layout: one scs:claim:<id> key holds the JSON for the entire claim (chunks, members, bans, perms, flags), and every chunk gets a lightweight scs:chunk:<worldUuid>;<x>;<z> pointer containing just the claim id. This makes a radius claim O(chunks) on the wire instead of O(chunks²) and avoids the SETEX timeouts that earlier layouts could trigger.

When should I enable it?

Redis is worth enabling when:

  • Caffeine evicts frequently (very large claim counts, a lot of Caffeine misses). Redis keeps deserialised claims close to the server.
  • You want claim reloads after a /scs reload to be fast (Redis survives the restart; Caffeine does not).

For small/medium servers, Caffeine alone is enough. Redis adds operational overhead (another service to run) without meaningful gains.

Use /scs clearRedis to flush the plugin's Redis keys (e.g., after a manual MySQL edit). It does not touch other plugins' keys in the same logical database.

Redis is not a cross-server synchronization mechanism. If you modify a claim on server A, server B's Caffeine will still hold the old value until it expires — the plugin does not publish invalidation messages to other servers. For true cross-server coherence you'd need an additional pub/sub layer, which the plugin does not implement.

Cache Thread Pool

Both the claim cache and the player cache share a tunable executor. It controls how many concurrent DB/Redis lookups the cache layer can fire when something misses Caffeine. Defaults are usually fine — only change this if you see "executor saturated" warnings or if your server is particularly large.

cache:
  thread-pool:
    # automatic = suitable for the machine (max(2, CPU cores / 2)).
    # manual    = use core-size below.
    mode: automatic
    core-size: 4
    queue-size: 5000

Key reference

KeyDescription
modeautomatic scales the pool against the host's CPU count. manual uses the configured core-size verbatim.
core-sizeAlways-alive threads per cache (claim + player). Only read in manual mode. Range 2–8 is typical.
queue-sizeHow many pending lookups the executor buffers before overflow. Overflow runs on the caller thread — visible as a brief stall rather than a lost task.

The claim cache and the player cache use independent executors but read the same config, so both stay sized consistently. Change it once, both are affected on next reload.

Discord Webhook

SCS2 can send notifications to a Discord channel when claim events occur (claims, unclaims, sales, purchases, etc.):

discord-webhook:
  enabled: false
  url: ""

Set enabled: true and paste your Discord webhook URL. Events like claiming, unclaiming, buying, selling, ban/kick actions, and new /requnclaim submissions are sent as embeds to the configured channel.

Web Dashboard

The admin web dashboard provides remote management of claims and players through a browser interface:

web-dashboard:
  enabled: false
  port: 8095
  # Public URL appended with ?token=<...> in the in-game login link.
  # Change this when the dashboard is behind a reverse proxy or a custom domain.
  url: "http://localhost:8095"
  # Token lifetime in hours. 0 = tokens never expire.
  token-ttl-hours: 24
  # Allowed CORS origins. Fallback: localhost + 127.0.0.1 on the configured port.
  # "*" means "any origin": insecure, only for local trusted setups.
  cors-origins:
    - "http://localhost:8095"
    - "http://127.0.0.1:8095"

Key reference

KeyDescription
enabledStarts the embedded HTTP server on plugin load.
portTCP port the dashboard listens on.
urlPublic URL sent in the in-game /scs dashboard click-to-open link. The plain auth token is appended as a ?token=... query parameter so the player lands signed in. Change this when the dashboard is behind a reverse proxy or a custom domain.
token-ttl-hoursHow long an issued admin token stays valid, in hours. 0 disables expiration so a token only stops working when manually rotated.
cors-originsWhitelist of Origin header values the dashboard will send CORS-allow headers for. Incoming requests whose Origin doesn't match are silently denied at the browser level.

Generate a login link

Run /scs dashboard in-game. The plugin sends a clickable [Click here] link in chat that opens the dashboard URL (from web-dashboard.url above) with the auth token already baked into the query string, so you land directly inside the dashboard. The token is also persisted in the browser's localStorage so a manual refresh keeps you signed in.

Tokens are stored hashed in web-tokens.json and persist across restarts.

Built-in abuse protection

  • Rate limiting — the /auth endpoint accepts at most 5 attempts per IP per minute. Further requests return HTTP 429 with a Retry-After header, making brute-force token guessing impractical.
  • Path traversal — static file requests are canonicalised; .. / ~ are rejected.
  • Prepared statements — all dashboard DB access goes through the same DAO layer, no raw SQL concatenation.

The dashboard uses plain HTTP (no built-in TLS). Tokens travel in clear text in the Authorization header, so never expose the port to the internet. Keep it bound to localhost (default) or put it behind a reverse proxy that terminates TLS.

On filesystems with multi-user access, consider restricting the web-tokens.json file (e.g., chmod 640). The tokens grant admin access to the dashboard.

Audit Logs

Track every action performed on claims for accountability and moderation:

audit-logs:
  enabled: false
  retention-days: 30
  # Buffer flush cadence (seconds). Lower = less data loss on a JVM crash, higher = fewer DB
  # roundtrips. The buffer is also flushed when batch-size entries accumulate, on /scs reload,
  # and on plugin disable.
  flush-interval-seconds: 5
  # Max entries kept in the in-memory buffer before forcing a flush.
  batch-size: 20

When enabled, all claim actions (permission changes, flag changes, member management, etc.) are logged with timestamps and player information. Logs older than retention-days are automatically purged.

Buffering

Writes do not hit the database one row at a time. Entries are buffered in memory and flushed in two cases: every flush-interval-seconds on a timer, or as soon as batch-size rows accumulate — whichever comes first. The buffer is also drained synchronously on /scs reload and on shutdown, so the only realistic data-loss window is a hard JVM crash within the last flush-interval-seconds seconds.

Exporting logs to CSV

/scs exportAuditLogs <claimId|*>

Dumps the audit log of a specific claim — or all claims with * — into a CSV file under plugins/SimpleClaimSystem/audit-exports/. Useful for external review, compliance, or just keeping a copy before retention-days drops old rows.

Claims Settings

claims:
  # Auto-purge inactive claims
  auto-purge:
    enabled: true
    checker: 1h
    time-without-login: 90d
    # Days before purge to start warning the affected owner on join. 0 = no warning.
    warn-days-before: 7

  # Allow /claim respawn (see Claiming > Respawn in Claim)
  respawn-in-claim:
    enabled: false

  # /claim back scope. false = any visited claim. true = only the player's own claims.
  claim-back:
    only-own-claims: false

  # Confirmation prompts — action must be run twice to execute
  confirmation:
    claim: false
    unclaim: false
    addchunk: false
    delchunk: false
    merge: false
    owner: true
  confirmation-delay: 30

  # Protection violation delivery: CHAT | ACTIONBAR | TITLE | NONE
  protection-message: CHAT

  # Particles
  show-particles: true
  show-particles-for-bedrock: false

  # Names & descriptions
  template-name: "claim-%n"
  max-length-name: 32
  allowed-regex-name: "^[a-zA-Z0-9]+$"
  max-length-description: 64
  allowed-regex-description: "^[a-zA-Z0-9\\s]+$"
  blocked-words: ["fuck", "asshole"]

  invitation-delay: 120               # seconds before an invite expires
  only-adjacent-chunks: false
  addchunk-instead-if-possible: false

  # Default metadata applied to every new claim
  default:
    isBuyable: false
    price: 0.0
    icon: FARMLAND
    particles: false
    warp: false       # public warp closed by default (toggle via /claim settings)
    visitPrice: 0.0   # /claim visit fee charged to visitors (0 = free)

  # Plugin message channels — each has independent enter / leave toggles.
  messages:
    chat:
      enter: false
      leave: false
    actionbar:
      enter: true
      leave: true
    title:
      enter: false
      leave: false

  # Claim economy (requires Vault)
  economy:
    enabled: true
    max-price: 1_000_000_000
    formatted-number: true
    # /claim sell broadcast channels.
    announce:
      chat: true
      actionbar: false
      title: false
      bossbar:
        enabled: true
        color: YELLOW
        overlay: PROGRESS

Key reference

KeyDescription
auto-purge.enabledRun the periodic purge job that deletes claims from long-inactive owners (players with auto-purge-bypass = true are skipped).
auto-purge.checkerHow often the purge runs. Format: 30m, 1h, 12h, 1d.
auto-purge.time-without-loginInactivity threshold. Same format as above.
auto-purge.warn-days-beforeHow many days before purge a doomed owner gets an in-game warning on join. 0 disables the warning.
respawn-in-claim.enabledMaster toggle for the /claim respawn feature (see Respawn in Claim).
claim-back.only-own-claimsfalse: /claim back can teleport to any claim the player walked into this session. true: only their own.
messages.<channel>.enter / messages.<channel>.leaveClaim enter/leave notification toggles, per channel (chat, actionbar, title). Each channel × direction is independent — e.g. greet players on enter via actionbar.enter: true without spamming them again on leave by leaving actionbar.leave: false. Any combination can be enabled. Schema change in 2.5.0: the old single-boolean form (messages.chat: true) was replaced by a nested enter/leave pair. Existing installs are auto-migrated by the config updater — the old leaf is replaced with the new section seeded from the bundled defaults.
confirmation.*Per-action confirmation prompts. When true, the player must re-run the command within confirmation-delay seconds.
confirmation-delaySeconds after which a pending confirmation expires.
protection-messageWhere the "you don't have permission" message appears when a player's action is blocked. CHAT, ACTIONBAR, TITLE or NONE.
show-particlesGlobal on/off for the continuous claim-boundary particles shown to claim members.
show-particles-for-bedrockWhen false, Bedrock clients (Geyser/Floodgate) never receive the continuous particles. They can stutter with dense particle loads.
template-nameDefault auto-generated name for new claims. %n → claim id, %player% → owner name.
max-length-name / allowed-regex-nameHard cap and regex enforced on claim names (same validation is applied by /claim create <name> and /claim setname).
max-length-description / allowed-regex-descriptionSame rules for claim descriptions. The default regex allows spaces.
blocked-wordsList of substrings: any claim name or description containing one of these is rejected.
invitation-delaySeconds before a pending /claim invite expires.
only-adjacent-chunksWhen true, a new chunk added to a claim must touch one of the claim's existing chunks. Prevents scattered layouts.
addchunk-instead-if-possibleWhen true, running /claim next to an existing owned claim adds the current chunk to that claim instead of creating a new one.
default.isBuyable / default.priceSale flags auto-applied to new claims. Usually kept at false / 0.0; the owner toggles with /claim sell.
default.iconMaterial shown as the claim icon in the claim-list GUI. Any Material enum.
default.particlesWhether the boundary-particle display is on by default for new claims.
default.warpWhether new claims open as public warps (visitable through /claim visit). Usually false — owners opt in via /claim settings.
default.visitPriceDefault Vault fee charged on every /claim visit, paid to the owner. 0.0 = free. Owners override per claim with /claim setvisitprice.
economy.enabledMaster toggle for claim economy. Requires Vault + an economy plugin.
economy.max-priceHard cap on any /claim sell price.
economy.formatted-numberWhen true, large prices display as 1,000,000 instead of 1000000.
economy.announce.chat / actionbar / title / bossbarPer-channel toggles for the /claim sell broadcast. The bossbar sub-block also takes color and overlay.

BossBar & Sounds

A BossBar is displayed when players are inside a claim (one color per role) and, optionally, when they are outside any claim (one color per world mode). Available colors: PINK, BLUE, RED, GREEN, YELLOW, PURPLE, WHITE. Available overlays: PROGRESS, NOTCHED_6, NOTCHED_10, NOTCHED_12, NOTCHED_20.

claims:
  bossbar:
    enabled: true
    # Outside any claim. Color/overlay/progress are configured per world mode.
    always-visible:
      survival-mode:
        enabled: true
        color: WHITE
        overlay: PROGRESS
        progress: 1.0
      survival_requiring_claims-mode:
        enabled: true
        color: WHITE
        overlay: PROGRESS
        progress: 1.0
      protected-mode:
        enabled: true
        color: GREEN
        overlay: PROGRESS
        progress: 1.0
      disabled-mode:
        enabled: true
        color: RED
        overlay: PROGRESS
        progress: 1.0
    # Inside a claim — one block per role.
    visitor:
      color: WHITE
      overlay: PROGRESS
      progress: 1.0
    member:
      color: GREEN
      overlay: PROGRESS
      progress: 1.0
    moderator:
      color: PURPLE
      overlay: PROGRESS
      progress: 1.0
    owner:
      color: BLUE
      overlay: PROGRESS
      progress: 1.0

Sounds

SCS2 ships 38 configurable sounds for every action: claiming, unclaiming, teleporting, entering/leaving claims, banning, kicking, merging, flying, inviting, and more. Each sound can be individually configured or disabled in claims.sounds.*.

Sound keys use Minecraft's dot notation (e.g., minecraft:ui.button.click, minecraft:entity.experience_orb.pickup). Set a sound to empty or remove it to disable it for that action.

Map Integration

SCS2 supports Dynmap, BlueMap, Pl3xMap, and squaremap with fully customizable visual styles:

dynmap:
  enabled: true
  show-labels: true
  styles:
    normal:
      line-weight: 2
      line-opacity: 0.8
      line-color: "00FF00"
      fill-opacity: 0.3
      fill-color: "00FF00"
      label-format: "%claim_name%"
    for-sale:
      line-color: "FFCC00"
      fill-color: "FFCC00"

Normal claims and for-sale claims can have different visual styles on the map. The same structure applies for bluemap, pl3xmap, and squaremap sections.

Default Player Settings

Values under players.default are copied to each player the first time they join. Existing players are migrated lazily — when their data is loaded, any missing key from this block is added automatically (no server-wide scan needed).

players:
  default:
    # Auto-actions — toggle via /claim auto-*
    auto-claim: false
    auto-unclaim: false
    auto-addchunk: false
    auto-delchunk: false
    auto-merge: false
    auto-fly: false
    auto-map: false

    # Hard ownership limits (0 = unlimited)
    max-claims: 0
    max-chunks: 1
    max-radius: 1

    # Default radius applied to /claim with no argument (and /claim create <name>).
    # 0 = single chunk. 1+ = behave like /claim radius N. Capped at max-radius.
    default-claim-radius: 0

    # Internal — id of the claim selected with /claim respawn. 0 = none. Do not edit by hand.
    respawn-claim-id: 0

    # Internal — sentinel for the last successful tax debit. The default is the literal
    # string "none" (player never taxed); the job replaces it with an epoch ms timestamp
    # after the first debit. Do not edit by hand.
    last-tax-paid: "none"

    # Economy (only active when claims.economy.enabled = true)
    chunk-cost: 0.0
    cost-multiplier: 1.0
    max-claim-price: 0.0

    # Membership / role limits (per claim)
    max-members: 3
    max-roles: 3

    # Misc gameplay
    distance: 1     # min chunk distance between this player's claims and other players'
    delay: 5        # teleport delay in seconds (/claim tp, menu tp, etc.)
    fly: 0          # remaining claim-fly seconds; replenished via /scs player commands

    # /claim auto-X anti-abuse timers (seconds). 0 disables.
    auto-default-timer: 0   # default timer when no [seconds] passed
    auto-max-timer: 0       # hard cap on player-supplied [seconds]

    # When true, the auto-purge job skips this player even if inactive
    auto-purge-bypass: false

Key reference

KeyTypeDescription
auto-*booleanPlayer-opt-in modes. Keep at false — players toggle them with /claim auto-*.
max-claimsintMaximum number of separate claims. 0 = unlimited.
max-chunksintMaximum total chunks across all claims. 0 = unlimited.
max-radiusintMaximum value for /claim radius <n>. The claimed bounding box has side = 2n+1.
default-claim-radiusintPlayer's default radius when typing /claim alone. 0 = single chunk. Capped at max-radius so raising it cannot bypass the limit.
respawn-claim-idintInternal — id of the claim the player respawns in (set via /claim respawn). 0 = no respawn claim. Do not edit manually.
last-tax-paidstring / longInternal — sentinel for the last successful tax debit (see Daily Tax / Rent). Defaults to the literal string "none" for players who have never been taxed; replaced with an epoch ms timestamp after the first debit. Do not edit manually.
chunk-costdoubleFlat economy cost per chunk claimed/added.
cost-multiplierdoubleCost multiplier applied as the claim grows (see Chunk Costs).
max-claim-pricedoubleHard cap on /claim sell price. 0 = no cap.
max-membersintMaximum members per claim. 0 = unlimited.
max-rolesintMaximum custom roles per claim. 0 = unlimited.
distanceintMinimum chunk distance enforced between this player's claims and other players' claims.
delayintTeleport delay in seconds before /claim tp / menu teleports execute.
flyintRemaining claim-fly time in seconds; replenished via admin commands.
auto-default-timerintAnti-abuse default timer (seconds) applied when the player runs /claim auto-X without an explicit [seconds]. 0 = no timer (mode stays on until toggled off). Permission override: scs.limit.auto-default-timer.<n>.
auto-max-timerintHard cap on the [seconds] a player can pass to /claim auto-X. 0 = no cap. Permission override: scs.limit.auto-max-timer.<n>.
auto-purge-bypassbooleanWhen true, the player is skipped by the claims.auto-purge job even if inactive.

Any of these can be overridden per player via permissions or admin commands — see the Limits page.

Plugin Hooks

Every optional integration can be disabled with a single flag in config.yml. Useful when another plugin is installed for its own reasons and you don't want SCS2 talking to it, or when troubleshooting ("does this still happen with the Dynmap hook off?").

hooks:
  vault: true              # economy (claim buy/sell, tax)
  worldguard: true         # registers the scs-claim custom flag
  placeholderapi: true     # %scs_*% placeholders
  geyser: true             # Bedrock client detection
  floodgate: true          # Bedrock UUID mapping
  dynmap: true
  bluemap: true
  pl3xmap: true
  squaremap: true
  quickshop-hikari: true
  griefprevention: true
  lands: true
  towny: true
  nexo: true               # <glyph:...> and <shift:N> tags
  oraxen: true
  itemsadder: true

Set any hook to false and SCS2 skips the entire setup — no retry timer, no listener registration, no performance cost. PacketEvents is a hard dependency and cannot be disabled here.

Disabling the vault hook automatically forces claims.economy.enabled to false (can't have economy features without an economy provider). Disabling map hooks removes the overlay; it doesn't delete stored claim geometry.

Bedrock Players

When Geyser/Floodgate is installed, SCS2 detects Bedrock clients and routes them through native forms (SimpleForm / CustomForm) instead of the Java chest GUIs. Two knobs control this:

bedrock:
  # true  → Bedrock players see the Java chest GUIs (translated by Geyser).
  # false → Bedrock players see the native forms defined under bedrock-guis/*.yml.
  force-java-menus: false

When to enable force-java-menus

  • Your resource pack uses Nexo/Oraxen glyphs that don't render on native Bedrock forms.
  • You want visual parity between Java and Bedrock clients.
  • You've customized Java GUIs heavily and don't want to maintain two separate UI trees.

Caveat

Chest GUIs translated by Geyser have quirks: shift-click doesn't always fire, some items render without custom model data, and closing via "E" vs the native close button behaves differently. For anything complex, the native Bedrock forms (below) give a better UX.