Skip to main content

Statistics Export

The plugin can export achievement statistics for use with external tools, websites, and analytics systems.

Overview

When enabled, the plugin periodically exports:

  • Global statistics
  • Player leaderboards
  • Recent achievement unlocks

Configuration

Enable export in config.json:

"export": {
"enabled": true,
"intervalSeconds": 300,
"exportGlobalStats": true,
"exportLeaderboards": true,
"exportRecentUnlocks": true,
"leaderboardSize": 100,
"recentUnlocksSize": 50,
"includePlayerTotals": true
}

Configuration Options

OptionTypeDefaultDescription
enabledbooleanfalseEnable/disable export
intervalSecondsnumber300Export frequency (5 minutes default)
exportGlobalStatsbooleantrueInclude global statistics
exportLeaderboardsbooleantrueInclude player rankings
exportRecentUnlocksbooleantrueInclude recent unlock history
leaderboardSizenumber100Number of top players
recentUnlocksSizenumber50Number of recent unlocks
includePlayerTotalsbooleantrueInclude per-player totals

Export Location

Statistics are exported to:

plugins/achievements/export/
├── global_stats.json
├── leaderboard.json
└── recent_unlocks.json

Export Formats

Global Statistics

global_stats.json:

{
"exportTime": "2024-01-15T10:30:00Z",
"totalAchievements": 487,
"totalPlayers": 1250,
"totalUnlocks": 15847,
"categoryStats": {
"combat": {
"total": 49,
"unlocked": 3521
},
"progression": {
"total": 102,
"unlocked": 8234
},
"exploration": {
"total": 32,
"unlocked": 1892
},
"social": {
"total": 20,
"unlocked": 1456
},
"husbandry": {
"total": 29,
"unlocked": 512
},
"secret": {
"total": 37,
"unlocked": 232
}
},
"popularAchievements": [
{
"id": "first_blood",
"name": "First Blood",
"unlockCount": 1187
},
{
"id": "miner_1",
"name": "Novice Miner",
"unlockCount": 1052
}
],
"rareAchievements": [
{
"id": "playtime_1000h",
"name": "Millennium Player",
"unlockCount": 3
},
{
"id": "monster_hunter_5",
"name": "Monster Slayer",
"unlockCount": 12
}
]
}

Leaderboard

leaderboard.json:

{
"exportTime": "2024-01-15T10:30:00Z",
"leaderboard": [
{
"rank": 1,
"playerUuid": "550e8400-e29b-41d4-a716-446655440000",
"playerName": "TopPlayer",
"achievementCount": 412,
"percentage": 84.6,
"recentUnlock": "monster_hunter_5",
"titles": ["Monster Slayer", "Veteran", "Explorer"]
},
{
"rank": 2,
"playerUuid": "550e8400-e29b-41d4-a716-446655440001",
"playerName": "SecondPlace",
"achievementCount": 387,
"percentage": 79.5,
"recentUnlock": "playtime_500h",
"titles": ["Time Lord", "Master Miner"]
}
]
}

Recent Unlocks

recent_unlocks.json:

{
"exportTime": "2024-01-15T10:30:00Z",
"recentUnlocks": [
{
"playerUuid": "550e8400-e29b-41d4-a716-446655440000",
"playerName": "Steve",
"achievementId": "spider_hunter_3",
"achievementName": "Spider Hunter III",
"category": "combat",
"unlockTime": "2024-01-15T10:28:45Z"
},
{
"playerUuid": "550e8400-e29b-41d4-a716-446655440002",
"playerName": "Alex",
"achievementId": "first_blood",
"achievementName": "First Blood",
"category": "combat",
"unlockTime": "2024-01-15T10:27:12Z"
}
]
}

Use Cases

Website Integration

Display achievement statistics on your server website:

// Fetch and display leaderboard
fetch('/api/achievements/leaderboard.json')
.then(response => response.json())
.then(data => {
const leaderboard = data.leaderboard;
leaderboard.forEach(player => {
console.log(`#${player.rank} ${player.playerName}: ${player.achievementCount}`);
});
});

Discord Bot

Post achievement notifications to Discord:

// Watch for new unlocks
const previousUnlocks = loadPreviousUnlocks();
const currentUnlocks = loadCurrentUnlocks();

const newUnlocks = currentUnlocks.filter(u =>
!previousUnlocks.some(p =>
p.playerUuid === u.playerUuid && p.achievementId === u.achievementId
)
);

newUnlocks.forEach(unlock => {
sendDiscordMessage(`🏆 ${unlock.playerName} unlocked: ${unlock.achievementName}!`);
});

Analytics Dashboard

Track achievement trends over time:

// Store daily snapshots
const today = new Date().toISOString().split('T')[0];
const stats = loadGlobalStats();

database.insert({
date: today,
totalUnlocks: stats.totalUnlocks,
totalPlayers: stats.totalPlayers,
categoryBreakdown: stats.categoryStats
});

Competitive Events

Track event achievement progress:

// Filter leaderboard for event achievements
const eventAchievements = ['summer_event_1', 'summer_event_2', 'summer_event_3'];

const eventLeaderboard = players.map(player => ({
name: player.playerName,
eventScore: player.achievements.filter(a =>
eventAchievements.includes(a)
).length
})).sort((a, b) => b.eventScore - a.eventScore);

Performance Considerations

Export Frequency

  • Default: 5 minutes (300 seconds)
  • Minimum recommended: 60 seconds
  • For high-traffic servers: 10+ minutes

File Size

Approximate sizes:

  • global_stats.json: ~5-10 KB
  • leaderboard.json (100 players): ~20-50 KB
  • recent_unlocks.json (50 unlocks): ~10-20 KB

Disk I/O

  • Files are written atomically (temp file → rename)
  • No data loss during crashes
  • Consider SSD for frequent exports

Customization

Filtering Leaderboard

To exclude certain players (staff, test accounts), implement server-side filtering when reading the export.

Combining with Other Data

Join achievement data with other server statistics:

const achievements = loadLeaderboard();
const playtime = loadPlaytimeStats();
const economy = loadEconomyStats();

const combinedStats = achievements.map(player => ({
...player,
playtime: playtime.find(p => p.uuid === player.playerUuid)?.hours || 0,
balance: economy.find(p => p.uuid === player.playerUuid)?.balance || 0
}));

Troubleshooting

Export Not Working

  1. Check export.enabled is true
  2. Verify write permissions on export directory
  3. Check server logs for errors

Missing Players

  • Only players with at least 1 achievement appear
  • Players must have logged in since plugin installation

Stale Data

  • Check intervalSeconds setting
  • Verify server isn't paused/stopped
  • Ensure adequate server resources