Storage Systems

Complete guide to how EssentialsC stores data. Learn about the 7 SQLite databases, YAML configuration files, and JSON data files that power your server.

On This Page

Storage Overview

EssentialsC v4.0.0 uses a hybrid storage system optimized for performance and reliability. Data is distributed across 7 SQLite databases (down from 24 in v3.x), YAML configuration files, and simple JSON files for specific use cases.

Directory Structure
plugins/EssentialsC/
├── config.yml                    # Main configuration
├── economy.db                    # SQLite - Economy balances & transactions
├── warps.db                      # SQLite - Warp locations & usage stats
├── homes.db                      # SQLite - Player home locations
├── kits.db                       # SQLite - Kit claim tracking
├── nicks.db                      # SQLite - Player nicknames
├── auction.db                    # SQLite - Auction house listings & history
├── shop.db                       # SQLite - Shop purchase/sale history
├── spawn.yml                     # YAML - Spawn location
├── kits.yml                      # YAML - Kit definitions
├── bans.yml                      # YAML - Ban entries
├── mutes.yml                     # YAML - Mute entries
├── ignores.yml                   # YAML - Player ignore lists
├── flying_players.json           # JSON - Players with fly mode enabled
├── scoreboards/
│   └── data.yml                  # YAML - Scoreboard disabled players
└── lang/                         # Directory - Language files
    ├── en_US.json
    ├── de_DE.json
    └── ... (30 total)

SQLite Databases (7 Files)

All SQLite databases use WAL (Write-Ahead Logging) mode for better concurrency and performance. Each database is accessed through the unified Database class with async query support.

economy.db SQLite Database Created on first run

Stores player economy balances and transaction history. Uses the Database class with async operations via CompletableFuture.

Schema
-- Player balances table
CREATE TABLE IF NOT EXISTS balances (
    uuid TEXT PRIMARY KEY,
    balance DECIMAL(19,2) NOT NULL DEFAULT 0.00
);

-- Transaction history for logging
CREATE TABLE IF NOT EXISTS transactions (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    uuid TEXT NOT NULL,
    amount DECIMAL(19,2) NOT NULL,
    type TEXT NOT NULL,        -- 'deposit', 'withdraw', 'transfer'
    source TEXT,               -- 'shop', 'auction', 'player', etc.
    timestamp INTEGER DEFAULT (strftime('%s', 'now'))
);

CREATE INDEX IF NOT EXISTS idx_transactions_uuid ON transactions(uuid);
warps.db SQLite Database Created on first run

Managed by WarpManager. Stores warp locations, permissions, costs, and per-player usage statistics. Warps are cached in memory on load for fast access.

Schema
-- Warp definitions
CREATE TABLE IF NOT EXISTS warps (
    name TEXT PRIMARY KEY,
    world TEXT NOT NULL,
    x REAL NOT NULL,
    y REAL NOT NULL,
    z REAL NOT NULL,
    yaw REAL NOT NULL,
    pitch REAL NOT NULL,
    permission TEXT,           -- Optional permission node
    cost REAL DEFAULT 0.0,     -- Economy cost to use
    hidden INTEGER DEFAULT 0,  -- 1 = hidden from lists
    description TEXT DEFAULT '',
    category TEXT DEFAULT 'default'
);

-- Per-player warp usage tracking
CREATE TABLE IF NOT EXISTS player_warp_usage (
    uuid TEXT NOT NULL,
    warp_name TEXT NOT NULL,
    uses INTEGER DEFAULT 0,
    last_used INTEGER DEFAULT 0,
    PRIMARY KEY (uuid, warp_name)
);
homes.db SQLite Database Created on first run

Managed by HomeManager. Stores player home locations with support for multiple homes per player (based on permissions). Uses async database operations for all queries.

Schema
-- Home locations
CREATE TABLE IF NOT EXISTS homes (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    uuid TEXT NOT NULL,
    name TEXT NOT NULL,
    world TEXT NOT NULL,
    x REAL NOT NULL,
    y REAL NOT NULL,
    z REAL NOT NULL,
    yaw REAL NOT NULL,
    pitch REAL NOT NULL,
    created_at INTEGER DEFAULT (strftime('%s', 'now')),
    UNIQUE(uuid, name)       -- One home name per player
);

CREATE INDEX IF NOT EXISTS idx_homes_uuid ON homes(uuid);
kits.db SQLite Database Created on first run

Managed by KitManager. Tracks kit claims, cooldowns, and usage counts. Kit definitions themselves are stored in kits.yml - this database only tracks player claim data.

Schema
-- Kit claim tracking
CREATE TABLE IF NOT EXISTS kit_claims (
    uuid TEXT NOT NULL,
    kit_name TEXT NOT NULL,
    last_claimed INTEGER DEFAULT 0,   -- Unix timestamp
    claim_count INTEGER DEFAULT 0,    -- Total times claimed
    PRIMARY KEY (uuid, kit_name)
);
nicks.db SQLite Database Created on first run

Managed by NickManager. Stores player nicknames with case-insensitive lookup support. Nicknames are cached in memory and applied on player join.

Schema
-- Player nicknames
CREATE TABLE IF NOT EXISTS nicknames (
    uuid TEXT PRIMARY KEY,
    nickname TEXT NOT NULL,           -- MiniMessage formatted
    updated_at INTEGER DEFAULT (strftime('%s', 'now'))
);

-- Index for nickname lookup (case-insensitive)
CREATE INDEX IF NOT EXISTS idx_nick_name ON nicknames(nickname);
auction.db SQLite Database Created on first run

Managed by AuctionManager. Stores active auctions, expired items, and transaction history. Items are serialized to Base64 for storage.

Schema
-- Active auctions
CREATE TABLE IF NOT EXISTS auctions (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    seller_uuid TEXT NOT NULL,
    seller_name TEXT NOT NULL,
    item_base64 TEXT NOT NULL,        -- Serialized ItemStack
    price REAL NOT NULL,
    listed_time INTEGER NOT NULL,     -- Unix timestamp
    duration INTEGER NOT NULL,        -- Duration in milliseconds
    claimed BOOLEAN DEFAULT FALSE     -- True when sold/cancelled/expired
);

-- Expired/unsold items waiting for pickup
CREATE TABLE IF NOT EXISTS expired_auctions (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    seller_uuid TEXT NOT NULL,
    item_base64 TEXT NOT NULL,
    expired_time INTEGER NOT NULL,
    claimed BOOLEAN DEFAULT FALSE
);
shop.db SQLite Database Created on first run

Managed by ShopDatabase. Logs all shop transactions for economy tracking and audit purposes. Shop configuration is in shop/ directory.

Schema
-- Purchase history
CREATE TABLE IF NOT EXISTS purchase_history (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    uuid TEXT NOT NULL,
    item_id TEXT NOT NULL,            -- Shop item identifier
    amount INTEGER NOT NULL,
    price DECIMAL(19,2) NOT NULL,
    timestamp INTEGER DEFAULT (strftime('%s', 'now'))
);

-- Sale history (players selling to shop)
CREATE TABLE IF NOT EXISTS sell_history (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    uuid TEXT NOT NULL,
    item_id TEXT NOT NULL,
    amount INTEGER NOT NULL,
    price DECIMAL(19,2) NOT NULL,
    timestamp INTEGER DEFAULT (strftime('%s', 'now'))
);

CREATE INDEX IF NOT EXISTS idx_purchases_uuid ON purchase_history(uuid);

YAML Configuration Files

YAML files store configuration data that needs to be human-readable and easily editable. These files are loaded into memory and cached for performance.

config.yml Main Configuration Auto-generated

Primary configuration file containing all plugin settings. Loaded by ConfigManager. Supports hot-reloading via /essc reload.

YAML
debug: true

default-language: en_US

heal:
  feed-player: true
  clear-negative-effects: true

economy:
  enabled: true
  starting-balance: "100.00"
  currency:
    singular: "Dollar"
    plural: "Dollars"
  minimum-transaction: "0.01"
  max-balance: -1

teleport:
  tpa:
    cooldown: 60
    warmup: 3
    timeout: 60
    max-pending: 5
    max-outgoing: 1
    cost: 0.0
    deny-movement: true
    particles: true
    sounds: true
    blocked-worlds: []

home:
  max-homes: 3
  default-name: "home"
  cooldown: 5
  warmup: 3
  cancel-on-movement: true
  particles: true
  sounds: true
  blocked-worlds:
    - "world_nether"
    - "world_the_end"

spawn:
  cooldown: 5
  warmup: 3
  teleport-on-first-join: true
  particles: true
  sounds: true
  cancel-on-movement: true

join-leave-messages:
  enabled: true
  join: "<white><player> <#FFCE00>joined the game"
  leave: "<white><player> <#FF4000>left the game"

back:
  warmup: 3
  cooldown: 5
  particles: true
  sounds: true
  cancel-on-movement: true

scoreboard:
  enabled: true
  update-interval: 20
  title: "<#FF3000><b>MyServer"
  lines:
    - ""
    - "<#FF3000>| <white>Player: <#FFAC96>%player_name%"
    - "<#FF3000>| <white>Rank: <#FFAC96>%luckperms_prefix%"
    - "<#FF3000>| <white>Balance: <#FFAC96>%vault_eco_balance_formatted%"
    - "<#FF3000>| <white>Online: <#FFAC96>%server_online%<gray>/<#FFAC96>%server_max_players%"
    - "<#FF3000>| <white>Kills: <#FFAC96>%statistic_player_kills%"
    - ""
    - "<#FFAC96>play.myserver.net"

rename:
  blacklist-enabled: true
  blacklist-words:
    - "badword"
    - "hello"
  max-length: 50
  min-length: 1
  normalize-enabled: true
  strip-colors-for-check: true

vanish:
  hide-from-tab: true
  give-night-vision: true
  prevent-mob-target: true
  disable-collisions: true

nickname:
  enabled: true
  min-length: 3
  max-length: 16
  allow-colors: true
  allow-formats: true
  blacklist-enabled: true
  blacklist-words: []
  normalize-enabled: true
  unique: true
  update-tab: true

shop:
  enabled: true
  main-menu-title: "<#F52727><b>Server Shop"
  main-menu-size: 54
  category-title: "<#F52727><category>"
  category-menu-title: "<#F52727>Shop - <category>"
  close-button-enabled: true
  items-per-page: 28
  fill-empty-slots: true
  fill-material: "BLACK_STAINED_GLASS_PANE"
  log-transactions: true
  currency:
    singular: "Dollar"
    plural: "Dollars"

hat:
  blacklist-enabled: true
  blacklist-items:
    - bedrock
    - barrier
    - command_block
    - structure_void
    - jigsaw
    - light
  allow-blocks: false
  require-lore: false
  require-custom-name: false

auction-house:
  enabled: true
  max-auctions-per-player: 5
  duration-hours: 48
  min-price: "1.00"
  max-price: "-1"

warp:
  enabled: true
  cooldown: 5
  warmup: 3
  cancel-on-movement: true
  particles: true
  sounds: true
  blocked-worlds:
    - world_nether
    - world_the_end
  group-by-category: true
  max-name-length: 16
  limit-per-player:
    enabled: false
    max: 5

afk:
  enabled: true
  timeout-seconds: 300
  kick-timeout-seconds: 1800
  tab-placeholder-enabled: true
  tab-placeholder: "<color:#FF6B6B>[AFK]</color> "
  broadcast-enabled: true
  title-enabled: true
  title: "<color:#FF6B6B>You are now AFK</color>"
  subtitle: "<color:#FFE66D>Move to return</color>"
  prevent-damage: true
  prevent-mob-target: true
  prevent-pickup: true
  freeze-player: true
  blocked-commands:
    - spawn
    - home
    - tpa
    - tpahere
    - warp
    - shop
  list-show-location: true
  list-show-world: true
  list-sort-by: "time"
spawn.yml Location Data Auto-generated

Stores the server spawn location. Managed by SpawnManager. Set via /setspawn command.

Structure
spawn:
  world: world
  x: 0.0
  y: 64.0
  z: 0.0
  yaw: 0.0
  pitch: 0.0
kits.yml Kit Definitions Auto-generated

Defines all available kits, their items, cooldowns, and permissions. See Kit Configuration for full details. Item data is stored with full NBT support.

Structure
kits:
  starter:
    display-name: "<#2791F5>Starter Kit"
    description: "Basic items for new players"
    cooldown: 86400          # 24 hours
    one-time: false
    first-join: true         # Given automatically
    max-claims: 10
    items:
      - type: STONE_SWORD
        amount: 1
        name: "<#2791F5>Kit Starter"
        enchantments: {}
        unbreakable: false
        flags: []
        custom-model-data: 0
        nbt: {}
bans.yml & mutes.yml Punishment Data Auto-generated

Store active bans and mutes. Managed by PunishmentManager. Uses player UUID as key for persistence across name changes.

Structure
# bans.yml
550e8400-e29b-41d4-a716-446655440000:
  name: "Qssaf"
  reason: "Griefing spawn area"
  banner: "TinyHelius"
  time: 1704067200000        # When banned (Unix ms)
  expires: 1706659200000     # 0 = permanent

# mutes.yml (same structure)
550e8400-e29b-41d4-a716-446655440000:
  name: "_GodlyCow"
  reason: "Spam in chat"
  muter: "Lena"
  time: 1704067200000
  expires: 1704153600000     # Temporary mute
ignores.yml Social Data Auto-generated

Stores player ignore lists (who each player is ignoring). Managed by IgnoreManager. In-memory cache with periodic saves.

Structure
550e8400-e29b-41d4-a716-446655440000:
  ignored:
    - "660e8400-e29b-41d4-a716-446655440001"
    - "770e8400-e29b-41d4-a716-446655440002"
  lastName: "PlayerName"
scoreboards/data.yml Player Preferences Auto-generated

Stores list of players who have disabled the scoreboard. Only created if scoreboard.persistent is true in config.

Structure
disabled-players:
  - "550e8400-e29b-41d4-a716-446655440000"
  - "660e8400-e29b-41d4-a716-446655440001"
shop/main.yml & *.yml Shop Configuration Auto-generated

Shop configuration including categories, items, and GUI settings. Category files are stored directly in the shop/ folder (not in a categories/ subfolder).

Directory
shop/
├── main.yml        # Main shop settings
├── blocks.yml      # Building blocks category
├── tools.yml       # Tools category
└── food.yml        # Food category

JSON Files

Simple JSON files are used for lightweight data that doesn't require complex querying or relational structure.

flying_players.json Simple List Auto-generated

Stores UUIDs of players who had fly mode enabled when they logged out. Managed by FlyManager. Fly state is restored on next login (unless player has essentialsc.fly.disable-on-join permission).

Format
550e8400-e29b-41d4-a716-446655440000
660e8400-e29b-41d4-a716-446655440001
770e8400-e29b-41d4-a716-446655440002

Note: One UUID per line, plain text format (not structured JSON). File is rewritten on every player quit that has fly enabled.

lang/*.json Language Files 30 built-in languages

Translation files for all plugin messages. See Languages for full details. Files are extracted from the plugin jar on first run.

Structure
{
  "prefix": "[EssC]",
  "heal.success": " You have been fully healed!",
  "heal.success.others": " Successfully healed ",
  "error.no_permission": " You don't have permission to use this.",
  "error.missing_key": "Missing key: "
}

Migration from v3.x

EssentialsC v4.0.0 is a complete rewrite with breaking changes. Data from v3.x does NOT migrate automatically. You must start fresh or manually recreate data.

Migration Strategy Recommendation Manual

Recommended approach for server administrators upgrading from v3.x:

Steps
1. BEFORE upgrading, export important data:
   - Use v3.x commands to document warps (/warp list)
   - Export economy data to a ledger
   - Screenshot or document player homes

2. Stop the server completely

3. Backup your entire EssentialsC folder:
   cp -r plugins/EssentialsC plugins/EssentialsC-backup-v3

4. Delete old v3.x files (or move them aside):
   - All .db files (they're incompatible)
   - Old config.yml (structure changed)

5. Install EssentialsC v4.0.0 jar

6. Start server - new files will be generated

7. Manually recreate warps, kits, and spawn point

8. For economy: use /eco give commands to restore balances

Backup & Recovery

Regular backups are essential. All EssentialsC data is stored in standard formats that can be backed up while the server is running (SQLite WAL mode allows this).

Critical Files to Backup Priority List All .db files

Priority order for backups (most critical first):

Priority
# CRITICAL - Player data (backup daily)
economy.db          # Player balances - HIGH PRIORITY
homes.db            # Player homes - HIGH PRIORITY
nicks.db            # Player nicknames
kits.db             # Kit claim tracking

# IMPORTANT - Server data (backup weekly)
warps.db            # Warp locations
auction.db          # Active auctions
shop.db             # Transaction history

# CONFIGURATION - Backup when changed
config.yml          # Main settings
kits.yml            # Kit definitions
spawn.yml           # Spawn location
shop/               # Shop configuration
bans.yml            # Ban list
mutes.yml           # Mute list

# OPTIONAL - Can be regenerated
ignores.yml         # Player ignore lists
flying_players.json # Fly state (temporary)
scoreboards/data.yml # Scoreboard preferences
lang/               # Language files (from jar)
Backup Script Example Linux/Bash Daily cron job

Example backup script for automated daily backups:

Bash
#!/bin/bash
# EssentialsC Backup Script
# Add to crontab: 0 2 * * * /path/to/backup-essc.sh

DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/backups/essc/$DATE"
ESSC_DIR="/server/plugins/EssentialsC"

mkdir -p "$BACKUP_DIR"

# Copy all database files (SQLite supports hot backup)
cp "$ESSC_DIR"/*.db "$BACKUP_DIR/"

# Copy configuration files
cp "$ESSC_DIR"/*.yml "$BACKUP_DIR/"
cp -r "$ESSC_DIR/shop" "$BACKUP_DIR/"
cp -r "$ESSC_DIR/lang" "$BACKUP_DIR/"

# Optional: Upload to remote storage
# rclone sync "$BACKUP_DIR" remote:essc-backups

# Cleanup old backups (keep 7 days)
find /backups/essc -type d -mtime +7 -exec rm -rf {} +

echo "EssentialsC backup completed: $BACKUP_DIR"
Database Integrity Check Maintenance Weekly

SQLite databases can be checked for corruption using the integrity_check pragma. Run this if you suspect database issues:

SQLite
# Check database integrity (run from server console or SSH)
sqlite3 plugins/EssentialsC/economy.db "PRAGMA integrity_check;"

# Expected output: "ok"

# If corrupted, restore from backup immediately
# Do NOT attempt to repair - restore from known good backup

Performance Characteristics

Understanding how the storage systems perform helps with capacity planning and troubleshooting.

SQLite Databases

WAL mode enabled for concurrent reads/writes. Supports thousands of transactions per second. Each database is separate to prevent lock contention.

YAML Files

Loaded once at startup and cached in memory. Written only when data changes. Not suitable for high-frequency updates (use SQLite for that).

JSON Files

Simple append-only or full-rewrite files. Used for small datasets only. flying_players.json is rewritten on every relevant player quit.