Skip to content
Server & storage

Server & storage

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: []
  cc: []
  requnclaim: []
  viewrequnclaim: []

# Base commands to unregister entirely (see the key reference below)
disabled-commands: []

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. Since 2.7.3 an alias enforces the same permission as its base command, and the three extra commands (cc, requnclaim, viewrequnclaim) can be aliased too.
disabled-commandsBase commands to remove from the server entirely (claim, claims, unclaim, parea, scs, cc, requnclaim, viewrequnclaim). Frees the name for another plugin. If the disabled command has command-aliases entries, the first alias becomes its replacement command — e.g. disable claims and set claims: [aclaims] to turn /claims into /aclaims while your own plugin takes over /claims. Restart required. (2.7.3) Changes apply on /scs reload when the server lets plugins unregister commands at runtime; otherwise the command stays hidden by the plugin and a restart applies the change fully. (2.8)

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
  ssl-mode: PREFERRED    # MySQL TLS: DISABLED, PREFERRED, REQUIRED, VERIFY_CA, VERIFY_IDENTITY
  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: 30000

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.
ssl-modeMySQL TLS mode: DISABLED, PREFERRED (default), REQUIRED, VERIFY_CA or VERIFY_IDENTITY. Ignored for SQLite. The connection URL is also hardened (allowLoadLocalInfile=false, utf8mb4). (2.7.3)
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. Default 30000; set 0 to disable. The pool is auto-sized to the engine (MySQL 20 / SQLite 4) with a 10s connection timeout. (2.7.3)

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, but since 2.8 it also doubles as a real-time cross-server sync bus (see Multi-server setup below): several servers sharing one Redis + one MySQL now see each other's claim changes instantly.

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
  username: ""                  # Redis 6+ ACL user; empty = default user
  password: ""                  # empty = no auth; set on any internet-facing Redis
  ssl: false                    # enable TLS to the Redis server
  cross-server-sync: true       # publish cache invalidations so other servers see changes live
  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.
usernameRedis 6+ ACL username. Leave empty to authenticate as the default user (password-only). (2.7.3)
passwordOptional AUTH password. Leave empty for unauthenticated Redis (only safe on localhost).
sslWhen true, connect to Redis over TLS. Keep Redis on a private network regardless. (2.7.3)
cross-server-syncWhen true (default), each server publishes a cache invalidation to the others on every claim mutation, so a change on one server appears on the rest in real time. Set false for a single server that wants zero pub/sub overhead. (2.8)
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.

Multi-server setup (2.8)

Point several servers at the same MySQL database and the same Redis, with redis.enabled: true and redis.cross-server-sync: true (the default). From then on the servers stay coherent in real time:

  • Every claim mutation (create, unclaim, add/remove chunk, rename, description, spawn, icon, members, roles, bans, permissions, flags, sale, ownership transfer) writes to MySQL + Redis, then publishes an invalidation on the scs:invalidate Redis channel.
  • Each other server is subscribed to that channel and, on receipt, drops the affected chunks from its local Caffeine cache, reads the fresh claim back from Redis and applies it: holograms, map markers, bossbars, the public-warp and spawn indexes and the per-player claim lists are all refreshed on the spot, so the change shows up within milliseconds, without a reload or a reconnect.
  • Per-player data travels on the same channel: every write to a player's data (limits, settings, purge grace, tax meter, favourites) publishes an invalidation, and a player's data is always re-read at login, so a change made on one server is visible on the others right away — including for a player currently connected elsewhere.
  • Unclaim requests, template names and claim-name lists are kept in step the same way, and a bulk rewrite (config migration, custom flag backfill, admin reset) sends a single flush that makes every server reload its cached claims.
  • The recurring jobs that must run once per network (tax collector, auto-purge, temporary-member sweep, unclaim-request sweep) take a short Redis lock before each run, so only one server executes them per interval and nobody is billed or purged twice.
  • A server ignores its own messages (each instance has a random id), so there is no echo loop, and cache warm-up loads (login, /scs reload) do not broadcast, so the channel stays quiet.
# Same config on every server:
database:
  enabled: true            # one shared MySQL
  # ...same host/name/credentials everywhere...
redis:
  enabled: true            # one shared Redis
  cross-server-sync: true
  # ...same host everywhere...

What syncs instantly: everything about claims (the map, protections, members, permissions, flags, sales, ownership, holograms, public warps) and everything about players (limits, settings, purge grace, tax meter, favourites), plus unclaim requests and claim templates. What stays local by design: pending invitations, claim chat and the anti-abuse timers of the /claim auto-* commands, which only make sense on the server the player is connected to.

Cross-server sync needs Redis. Without it (redis.enabled: false), each server only has its local Caffeine cache and will not see another server's claim changes until the cache expires — so a multi-server deployment should always run a shared Redis.

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.