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.
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.
Stores player economy balances and transaction history. Uses the Database class with async operations via CompletableFuture.
-- 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);
Managed by WarpManager. Stores warp locations, permissions, costs, and per-player usage statistics. Warps are cached in memory on load for fast access.
-- 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)
);
Managed by HomeManager. Stores player home locations with support for multiple homes per player (based on permissions). Uses async database operations for all queries.
-- 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);
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.
-- 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)
);
Managed by NickManager. Stores player nicknames with case-insensitive lookup support. Nicknames are cached in memory and applied on player join.
-- 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);
Managed by AuctionManager. Stores active auctions, expired items, and transaction history. Items are serialized to Base64 for storage.
-- 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
);
Managed by ShopDatabase. Logs all shop transactions for economy tracking and audit purposes. Shop configuration is in shop/ directory.
-- 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.
Primary configuration file containing all plugin settings. Loaded by ConfigManager.
Supports hot-reloading via /essc reload.
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"
Stores the server spawn location. Managed by SpawnManager. Set via /setspawn command.
spawn:
world: world
x: 0.0
y: 64.0
z: 0.0
yaw: 0.0
pitch: 0.0
Defines all available kits, their items, cooldowns, and permissions. See Kit Configuration for full details. Item data is stored with full NBT support.
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: {}
Store active bans and mutes. Managed by PunishmentManager. Uses player UUID as key for persistence across name changes.
# 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
Stores player ignore lists (who each player is ignoring). Managed by IgnoreManager. In-memory cache with periodic saves.
550e8400-e29b-41d4-a716-446655440000:
ignored:
- "660e8400-e29b-41d4-a716-446655440001"
- "770e8400-e29b-41d4-a716-446655440002"
lastName: "PlayerName"
Stores list of players who have disabled the scoreboard. Only created if scoreboard.persistent is true in config.
disabled-players:
- "550e8400-e29b-41d4-a716-446655440000"
- "660e8400-e29b-41d4-a716-446655440001"
Shop configuration including categories, items, and GUI settings.
Category files are stored directly in the shop/ folder (not in a categories/ subfolder).
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.
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).
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.
Translation files for all plugin messages. See Languages for full details. Files are extracted from the plugin jar on first run.
{
"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.
Recommended approach for server administrators upgrading from v3.x:
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).
Priority order for backups (most critical first):
# 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)
Example backup script for automated daily backups:
#!/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"
SQLite databases can be checked for corruption using the integrity_check pragma. Run this if you suspect database issues:
# 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.