0, 'path' => '/intern/statistik/', 'secure' => true, 'httponly' => true, 'samesite' => 'Strict', ]); session_start(); $configPath = __DIR__ . '/stats-config.local.php'; if (!is_file($configPath)) { http_response_code(503); exit('Die interne Statistik ist noch nicht konfiguriert.'); } $config = require $configPath; if (isset($_GET['logout'])) { $_SESSION = []; session_destroy(); header('Location: ./'); exit; } $loginError = ''; if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['username'], $_POST['password'])) { $userOk = hash_equals((string) $config['username'], (string) $_POST['username']); $passwordOk = hash_equals((string) $config['password_sha256'], hash('sha256', (string) $_POST['password'])); if ($userOk && $passwordOk) { session_regenerate_id(true); $_SESSION['authenticated'] = true; header('Location: ./'); exit; } usleep(350000); $loginError = 'Anmeldung fehlgeschlagen.'; } function fetchJson(string $url, string $method = 'GET', ?string $body = null): ?array { if (function_exists('curl_init')) { $handle = curl_init($url); $options = [ CURLOPT_RETURNTRANSFER => true, CURLOPT_FOLLOWLOCATION => true, CURLOPT_CONNECTTIMEOUT => 4, CURLOPT_TIMEOUT => 8, CURLOPT_USERAGENT => 'GerGames-Internal-Stats/1.0', CURLOPT_HTTPHEADER => ['Accept: application/json', 'Content-Type: application/json'], CURLOPT_CUSTOMREQUEST => $method, ]; if ($body !== null) { $options[CURLOPT_POSTFIELDS] = $body; } curl_setopt_array($handle, $options); $response = curl_exec($handle); $status = (int) curl_getinfo($handle, CURLINFO_RESPONSE_CODE); curl_close($handle); if (!is_string($response) || $status < 200 || $status >= 300) return null; } else { $context = stream_context_create(['http' => [ 'method' => $method, 'timeout' => 8, 'ignore_errors' => true, 'header' => "Accept: application/json\r\nContent-Type: application/json\r\nUser-Agent: GerGames-Internal-Stats/1.0\r\n", 'content' => $body ?? '', ]]); $response = @file_get_contents($url, false, $context); if (!is_string($response)) return null; } $decoded = json_decode($response, true); return is_array($decoded) ? $decoded : null; } function e(string $value): string { return htmlspecialchars($value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); } if (empty($_SESSION['authenticated'])): ?> GerGames – Interne Statistik

Interne Statistik

Geschützter GerGames-Bereich

0, 'android' => 0]; foreach ($releases as $releaseIndex => $release) { if (!is_array($release)) continue; if ($releaseIndex === 0) $latestRelease = (string) ($release['name'] ?? $release['tag_name'] ?? 'Aktuelles Release'); foreach (($release['assets'] ?? []) as $asset) { if (!is_array($asset)) continue; $count = max(0, (int) ($asset['download_count'] ?? 0)); $downloadTotal += $count; if ($releaseIndex === 0) $latestDownloads += $count; $name = strtolower((string) ($asset['name'] ?? '')); if (substr($name, -4) === '.exe') $platformDownloads['windows'] += $count; if (substr($name, -4) === '.apk') $platformDownloads['android'] += $count; } } $playerStats = null; $httpKey = trim((string) ($config['nakama_http_key'] ?? '')); if ($httpKey !== '') { $statsUrl = (string) $config['nakama_rpc_url'] . '?http_key=' . rawurlencode($httpKey) . '&unwrap'; $rpcResponse = fetchJson($statsUrl, 'POST', '{}'); if (is_array($rpcResponse)) { $playerStats = $rpcResponse; if (isset($rpcResponse['payload']) && is_string($rpcResponse['payload'])) { $payload = json_decode($rpcResponse['payload'], true); if (is_array($payload)) $playerStats = $payload; } } } $players = (int) ($playerStats['total_players'] ?? 0); $today = gmdate('Y-m-d'); $activeToday = (int) (($playerStats['daily_active'] ?? [])[$today] ?? 0); $updatedAt = isset($playerStats['updated_at']) ? date('d.m.Y H:i', intdiv((int) $playerStats['updated_at'], 1000)) : 'Noch keine Daten'; ?> Void Bastion – Interne Statistik

GERGAMES · NICHT ÖFFENTLICH

Void Bastion Statistik

Abmelden
Downloads insgesamt
Downloads aktuelles Release
Registrierte Piloten
Heute aktive Piloten
Windows-Downloads
Android-Downloads

Die Downloadwerte stammen direkt aus den Gitea-Release-Anhängen und werden alle fünf Minuten neu geladen.

Die private Nakama-Statistik ist noch nicht mit dem HTTP-Schlüssel verbunden.

Letzte Spieleraktualisierung:

Diese Seite ist nicht verlinkt, von Suchmaschinen ausgeschlossen und verlangt eine Anmeldung. Es werden ausschließlich zusammengefasste Werte dargestellt.