Statistikportal für den All-the-Mods-10-Server (Minecraft 1.21.1, NeoForge 21.1): - mod/: serverseitige NeoForge-Mod atmstats – Ereignisse, Live-Zähler, Servergesundheit, FTB-Dateien; Outbox auf der Festplatte, signierter gzip-Versand per HTTPS mit Backoff - backend/: Fastify + PostgreSQL – idempotenter Ingest, Projektionen, Parser für SNBT, FTB Quests/Teams, world/stats, world/advancements und latest.log; Ranglisten, Snapshots, Retention, öffentliche API, SSE-Live-Updates, Admin mit argon2/CSRF, SFTP-Worker - web/: Next.js-Dashboard – Übersicht, Ranglisten, Spielerprofile, ATM10, Server, Datenquellen, Verwaltung - shared/: Protokoll v1 und API-Typen; tools/: Simulator, Log-Anonymisierer, RCON-Client - deploy/: Docker Compose hinter Traefik, Backup; docs/: Architektur, Datenquellen, Betrieb Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
154 lines
4.3 KiB
TypeScript
154 lines
4.3 KiB
TypeScript
// DTOs of the public read API, shared by backend and web.
|
|
|
|
export type Unit = 'hours' | 'count' | 'km' | 'blocks';
|
|
export type Period = 'all' | '30d' | '7d';
|
|
export type ItemCategory = 'mined' | 'crafted' | 'used' | 'picked_up';
|
|
export const ITEM_CATEGORIES: ItemCategory[] = ['mined', 'crafted', 'used', 'picked_up'];
|
|
|
|
export interface OverviewDto {
|
|
online: number;
|
|
totalPlayers: number;
|
|
totalPlayHours: number;
|
|
totalDeaths: number;
|
|
totalMobKills: number;
|
|
questsCompleted: number;
|
|
advancements: number;
|
|
lastUpdate: number | null;
|
|
}
|
|
|
|
export interface OnlinePlayerDto {
|
|
uuid: string;
|
|
name: string | null;
|
|
since: number;
|
|
dimension: string | null;
|
|
}
|
|
export interface OnlineDto {
|
|
players: OnlinePlayerDto[];
|
|
}
|
|
|
|
export interface BoardMetaDto {
|
|
id: string;
|
|
title: string;
|
|
description: string;
|
|
unit: Unit;
|
|
}
|
|
export interface LeaderboardEntryDto {
|
|
rank: number;
|
|
uuid: string;
|
|
name: string | null;
|
|
value: number;
|
|
}
|
|
export interface LeaderboardsDto {
|
|
boards: (BoardMetaDto & { top: LeaderboardEntryDto[] })[];
|
|
}
|
|
export interface LeaderboardDto {
|
|
board: BoardMetaDto;
|
|
period: Period;
|
|
entries: LeaderboardEntryDto[];
|
|
}
|
|
|
|
export interface PlayerListItemDto {
|
|
uuid: string;
|
|
name: string | null;
|
|
lastSeen: number | null;
|
|
playHours: number;
|
|
online: boolean;
|
|
}
|
|
export interface PlayerListDto {
|
|
players: PlayerListItemDto[];
|
|
total: number;
|
|
}
|
|
|
|
export interface PlayerQuestsDto {
|
|
teamId: string;
|
|
teamName: string | null;
|
|
completed: number;
|
|
total: number | null;
|
|
chapters: { chapterId: string; title: string | null; completed: number; total: number }[];
|
|
/** last completed quests that have a title in the quest config (newest first, max. 10) */
|
|
recent: { questId: string; title: string; chapterTitle: string | null; at: number }[];
|
|
}
|
|
|
|
export interface PlayerProfileDto {
|
|
uuid: string;
|
|
name: string | null;
|
|
firstSeen: number;
|
|
lastSeen: number | null;
|
|
online: boolean;
|
|
playHours: number;
|
|
sessions: number;
|
|
ranks: Record<string, { rank: number; value: number }>;
|
|
/** minecraft:custom counters except distances (raw values; play_time in ticks) */
|
|
general: Record<string, number>;
|
|
/** distances in cm by key (minecraft:walk_one_cm …) */
|
|
movement: Record<string, number>;
|
|
deathsByCause: { cause: string; count: number }[];
|
|
killedBy: { entity: string; count: number }[];
|
|
killsByType: { entity: string; count: number }[];
|
|
bossKills: { entity: string; at: number }[];
|
|
dimensions: { dimension: string; firstAt: number }[];
|
|
advancements: { id: string; title: string | null; at: number }[];
|
|
quests: PlayerQuestsDto;
|
|
/** minutes online per [weekday 0=Mon..6=Sun][hour 0..23], last 90 days, server time zone */
|
|
activityHeatmap: number[][];
|
|
}
|
|
|
|
export interface HistoryDto {
|
|
metric: string;
|
|
unit: Unit;
|
|
points: { t: number; v: number }[];
|
|
}
|
|
|
|
export interface ItemsDto {
|
|
category: ItemCategory;
|
|
mods: { namespace: string; total: number; items: { key: string; value: number }[] }[];
|
|
}
|
|
|
|
export interface ServerInfoDto {
|
|
startedAt: number;
|
|
mcVersion: string;
|
|
neoforgeVersion: string;
|
|
javaVersion: string;
|
|
modCount: number;
|
|
}
|
|
|
|
export interface ModsDto {
|
|
server: ServerInfoDto | null;
|
|
mods: { id: string; name: string; version: string; activity: number; category: string | null }[];
|
|
/** activity per category (tech/magic/farming/other) across all visible players */
|
|
categories: { category: string; activity: number }[];
|
|
}
|
|
|
|
export interface QuestsDto {
|
|
defsKnown: boolean;
|
|
chapters: { chapterId: string; title: string | null; total: number; maxCompleted: number; teamsFinished: number }[];
|
|
teams: { teamId: string; name: string | null; members: { uuid: string; name: string | null }[]; completed: number }[];
|
|
}
|
|
|
|
export interface HealthPointDto {
|
|
t: number;
|
|
msptAvg: number;
|
|
msptP95: number;
|
|
tps: number;
|
|
players: number;
|
|
heapUsedMb: number;
|
|
heapMaxMb: number;
|
|
}
|
|
export interface ServerDto {
|
|
info: ServerInfoDto | null;
|
|
health: HealthPointDto[];
|
|
}
|
|
|
|
export interface SourcesDto {
|
|
push: { lastEventAt: number | null; lastServerStart: number | null; reachable: boolean };
|
|
sftp: { enabled: boolean; lastSyncAt: number | null; lastError: string | null };
|
|
limitations: string[];
|
|
}
|
|
|
|
export type LiveKind = 'online' | 'death' | 'advancement' | 'quest' | 'counters';
|
|
export interface LiveEvent {
|
|
id: number;
|
|
kind: LiveKind;
|
|
data: Record<string, unknown>;
|
|
}
|