Database Setup
Erupe uses PostgreSQL. The schema is managed through three layers: a base dump, incremental patches, and optional demo data.
Initial Setup
Create the database and restore the base schema (pg_dump custom format, not plain SQL):
createdb -U postgres erupe
pg_restore -U postgres -d erupe schemas/init.sql
This bootstraps the schema to v9.1.0.
Patch Schemas
Apply all files in schemas/patch-schema/ in numerical order. Each patch is idempotent but must follow the previous ones:
for f in schemas/patch-schema/*.sql; do
psql -U postgres -d erupe -f "$f"
done
Notable patches:
| Patch | Effect |
|---|---|
00-psn-id.sql |
Adds PSN ID column to users |
02-tower.sql |
Adds Tower mode tables |
08-kill-counts.sql |
Adds kill_logs table |
10-rework-distributions.sql |
Migrates distribution system (deletes old distribution data) |
12-event_quest_cycling.sql |
Adds event quest rotation timestamps |
14-fix-fpoint-trades.sql |
Reworks FPoint shop (deletes old FPoint items) |
16-discord-password-resets.sql |
Adds Discord account linking columns |
Bundled Demo Data
Optional SQL files in schemas/bundled-schema/ populate game content. Load any you want:
psql -U postgres -d erupe -f schemas/bundled-schema/EventQuests.sql
| File | Content |
|---|---|
DistributionDemo.sql |
Gift box items (equipment, item box pages) |
DivaShops.sql |
Diva Defense shop items |
EventQuests.sql |
~200+ event quest definitions |
FestaDefaults.sql |
Festa prize tiers (personal/guild, soul thresholds) |
FPointItems.sql |
~100+ Frontier Point shop items |
GachaDemo.sql |
3 gacha examples (normal, step-up, box) |
NetcafeDefaults.sql |
Net Cafe bonus items |
OtherShops.sql |
Miscellaneous shop data |
RoadShopItems.sql |
Road shop unlockables |
ScenarioDefaults.sql |
Scenario counter initialization |
Key Tables
Users & Characters
| Table | Purpose |
|---|---|
users |
Accounts (bcrypt password, rights bitmask, PSN ID, Discord token) |
characters |
Character data with ~17 bytea savedata fields |
sign_sessions |
Active authentication tokens |
bans |
Ban records with optional expiry |
Game Content
| Table | Purpose |
|---|---|
distribution + distribution_items |
Gift box system (login bonuses, GM gifts) |
event_quests |
Event quest rotation (quest_type, quest_id, cycling timestamps) |
gacha_shop + gacha_entries + gacha_items |
Gacha lottery (normal, step-up, box) |
shop_items |
Shop inventory (cost, HR/SR/GR requirements) |
fpoint_items |
Frontier Point shop |
cafebonus |
Net Cafe time-based bonuses |
scenario_counter |
Scenario/cutscene unlock tracking |
Guilds (8 tables)
| Table | Purpose |
|---|---|
guilds |
Guild info (name, leader, RP, icon, recruiting) |
guild_characters |
Membership and roles |
guild_applications |
Pending invites/applications |
guild_posts |
Bulletin board |
guild_adventures |
Guild adventure tracking |
guild_hunts |
Guild hunt records |
guild_meals |
Guild meal cooking |
guild_alliances |
Inter-guild alliances |
Events
| Table | Purpose |
|---|---|
events |
Active events (type: festa/diva/vs/mezfes) |
festa_registrations |
Festa sign-ups |
festa_trials + festa_prizes |
Festa scores and rewards |
feature_weapon |
Daily featured weapon rotation |
tower |
Tower mode progress (TR, TRP, TSP) |
rengoku_score |
Rengoku survival scores |
kill_logs |
Monster kill tracking |
Common Admin Operations
Add an event quest
INSERT INTO event_quests (max_players, quest_type, quest_id, mark)
VALUES (4, 28, 23045, 2);
See Enumerations for quest type and mark values.
Create a gift distribution
INSERT INTO distribution (type, deadline, event_name, description, times_acceptable)
VALUES (1, '2099-12-31', 'Welcome Gift', 'A gift for new hunters', 1)
RETURNING id;
INSERT INTO distribution_items (distribution_id, item_type, item_id, quantity)
VALUES (<returned_id>, 7, 482, 10);
See Enumerations for type/item_type values.
Ban a user
INSERT INTO bans (user_id, expires_at)
VALUES (<user_id>, NOW() + INTERVAL '7 days');
Reset Raviente
SELECT ravireset(0);
Check active sessions
SELECT u.username, s.token FROM sign_sessions s
JOIN users u ON u.id = s.user_id;
Backup & Restore
Backup
# Full backup (custom format, recommended)
pg_dump -U postgres -Fc erupe > erupe_backup.dump
# Plain SQL backup
pg_dump -U postgres erupe > erupe_backup.sql
# Compressed plain SQL
pg_dump -U postgres erupe | gzip > erupe_backup.sql.gz
Restore
# From custom format
dropdb -U postgres erupe
createdb -U postgres erupe
pg_restore -U postgres -d erupe erupe_backup.dump
# From plain SQL
dropdb -U postgres erupe
createdb -U postgres erupe
psql -U postgres -d erupe -f erupe_backup.sql
# From compressed SQL
gunzip -c erupe_backup.sql.gz | psql -U postgres -d erupe
Maintenance
# Reclaim space and update query planner statistics
psql -U postgres -d erupe -c "VACUUM ANALYZE;"
# Check database size
psql -U postgres -d erupe -c "SELECT pg_size_pretty(pg_database_size('erupe'));"
Troubleshooting
| Error | Cause | Fix |
|---|---|---|
Connection refused |
PostgreSQL not running or wrong port | Verify service is running: systemctl status postgresql. Check Port in config. |
password authentication failed |
Wrong password or user | Verify Database.Password in config.json. Check user exists: psql -U postgres -c "\du" |
database "erupe" does not exist |
Database not created | Run createdb -U postgres erupe |
permission denied for table |
User lacks privileges | GRANT ALL ON ALL TABLES IN SCHEMA public TO <user>; |
| Server starts but data doesn't load | Schema patches missing or out of order | Re-apply patches in numerical order from schemas/patch-schema/ |
Performance Tuning
For servers with many concurrent players, consider tuning PostgreSQL:
# /etc/postgresql/*/main/postgresql.conf
shared_buffers = 2GB # 25% of available RAM
work_mem = 16MB # Per-operation memory
maintenance_work_mem = 512MB # For VACUUM, CREATE INDEX
For high connection counts, consider PgBouncer for connection pooling. Restart PostgreSQL after changing postgresql.conf.