Plugins verwalten

Plugins verwalten

Vollständige Anleitung zum Installiert-Tab — Anzeigen, Filtern, Aktualisieren, Aktivieren/Deaktivieren, Deinstallieren, Upload-Erkennung, ZIP-Export und alle möglichen Fehler.


Installierte Plugins Liste

Zwei Quellen:

  1. Browser-installiert — Vollständiges Tracking (Anbieter, Version, Plugin-ID, Download-URL, Update-Erkennung)
  2. Manuell hochgeladen — Vom Scanner automatisch erkannt, als „Manual / Upload" mit eingeschränktem Tracking registriert

Spalten

Spalte Beschreibung
Icon Anbieter-Logo (leer bei Uploads)
Name Aus JAR plugin.yml oder Dateiname (Versions-Regex entfernt)
Status Aktiv, Deaktiviert oder Unbekannt
Anbieter SpigotMC, CurseForge, Modrinth, Hangar, GeyserMC oder Upload
Version Installierte Versionsnummer
Installiert am Zeitstempel der Erstinstallation
Neueste Version Neueste verfügbare auf der Plattform (wenn getrackt)

Upload-Erkennung

scanAndRegisterUploadedPlugins() läuft automatisch:

  • Vergleicht JAR-Dateien auf der Festplatte (/plugins/) mit Datenbankeinträgen
  • Neue Dateien: Werden mit Anbieter 'upload' registriert. Öffnet JAR zum Extrahieren von plugin.yml für den Namen, oder parst Version aus Dateiname-Regex -(\d+\.\d+(?:\.\d+)?)
  • Gelöschte Dateien: Werden aus der Datenbank entfernt (Aufräumen)
  • Parallelitätsschutz: Atomare Sperre mit 10-Sekunden-TTL
  • Einschränkung: Upload-Plugins haben keine automatische Update-Erkennung

Anzeigename-Auflösung

Anbieter Namensquelle
GeyserMC Großgeschriebener Projektname
PaperMC Slug-Teil von Owner/Slug
CurseForge Slug wenn versionspräfiziert
Andere JAR plugin.yml → Dateiname-Fallback

Filtern

Filter Zeigt
Alle anzeigen Alle Plugins
Aktiv Nur aktivierte Plugins
Deaktiviert Nur deaktivierte Plugins (mit -bak Suffix)
Updates verfügbar Nur Plugins mit neueren Plattform-Versionen

Plugins mit Updates werden nach oben sortiert, dann alphabetisch.

Filter-Beibehaltung

Das Plugin nutzt resetTableKeepingFilters() — speichert den Filterzustand bevor Filament zurücksetzt, stellt ihn danach wieder her. Dies verhindert den Verlust des „has_updates"-Filters beim Navigieren.


Plugins aktualisieren

Wie die Update-Erkennung funktioniert

  • Plugin fragt die Quellplattform nach gespeicherter plugin_id und Anbieter ab
  • Update-Metadaten 24 Stunden gecacht pro Plugin
  • 'upload' Anbieter wird immer übersprungen
  • Zeichenkettenvergleich für Versions-IDs (kein Semantic Versioning)

Spezial: Update bei deaktiviertem Plugin

Wenn ein Plugin deaktiviert ist (hat -bak Suffix) wenn ein Update installiert wird:

  • Der is_disabled Status wird vor dem Update gemerkt
  • Nach dem Update wird das Plugin automatisch erneut deaktiviert
  • Dein Deaktiviert-Status bleibt über Updates erhalten

Konsolen-Widget

  • Synchronisiert Plugins beim Laden
  • Update-Prüfung mit 15-Minuten-Cache
  • Warnungs-Badge + Weiterleitungs-URL zum Plugin Browser
  • Gleiches Muster wie Game Mods Widget

Plugins aktivieren / deaktivieren

Mechanismus

Datei-Umbenennung über Lesen+Schreiben+Löschen (für Daemon-API-Kompatibilität):

Aktion Schritte Beispiel
Deaktivieren 1. Datei lesen 2. Als {name}-bak schreiben 3. Original löschen EssentialsX-2.20.jarEssentialsX-2.20.jar-bak
Aktivieren 1. -bak Datei lesen 2. Als Originalname schreiben 3. -bak löschen EssentialsX-2.20.jar-bakEssentialsX-2.20.jar

Hinweis: Drei Daemon-API-Aufrufe pro Umschaltung. Der Server muss möglicherweise vorher gestoppt werden.

Benachrichtigungen

Aktion Erfolg Fehler
Deaktivieren „Plugin disabled: [Name]" „Disable failed" + Fehler
Aktivieren „Plugin enabled: [Name]" „Enable failed" + Fehler

Plugins deinstallieren

Prozess

  1. Klicke Deinstallieren → Warnung bestätigen
  2. JAR-Datei wird aus /plugins/ gelöscht
  3. Datenbankeintrag wird entfernt
  4. Benachrichtigung: „Plugin uninstalled"
  5. Server neustarten um vollständig zu entladen

Was NICHT entfernt wird

Nicht entfernt Beispiel Aufräum-Methode
Konfigurationsdateien plugins/Essentials/config.yml Dateimanager
Datendateien plugins/LuckPerms/luckperms-*.db Dateimanager
Berechtigungen Berechtigungsknoten in LuckPerms etc. Berechtigungs-Plugin-UI
Weltdaten Eigene Strukturen, Blöcke Nicht umkehrbar

Plugins-Ordner öffnen

Springt zu /plugins/ im Dateimanager. Nützlich für:

  • Tatsächliche Dateien auf der Festplatte prüfen
  • Manuelle Uploads
  • Aufräumen von Konfigurationsverzeichnissen nach der Deinstallation
  • Überprüfen von -bak Erweiterungen bei deaktivierten Plugins

ZIP-Export

Prozess

  1. Klicke Alle als ZIP herunterladen
  2. Benachrichtigung: „ZIP download started"
  3. Server komprimiert alle Dateien in /plugins/
  4. JWT-signierte URL wird generiert (läuft nach 30 Minuten ab)
  5. Download startet automatisch

Enthält: Alle Plugins (aktive + deaktivierte)


Vollständige Fehlerreferenz

„Failed to read installed plugins"

  • /plugins/-Verzeichnis existiert nicht → Server einmal starten
  • Verzeichnis nicht lesbar → Daemon-Berechtigungen prüfen
  • Festplatte voll
  • Daemon-Verbindung verloren

„Failed to disable/enable plugin"

  • Berechtigungen: Lesen + Schreiben + Löschen erforderlich auf /plugins/
  • Datei gesperrt: Laufender Server sperrt Dateien → Server zuerst stoppen
  • Gleichzeitiger Zugriff: Backup oder Dateimanager greift gleichzeitig zu
  • Datei nicht gefunden: Extern umbenannt oder gelöscht
  • Daemon-Fehler: Jeder der 3 Schritte (Lesen/Schreiben/Löschen) kann fehlschlagen

„Failed to delete old versions"

  • Alte Datei vom laufenden Server gesperrt → Server stoppen
  • Dateiberechtigungsproblem
  • Datei bereits manuell entfernt

Updates werden nicht angezeigt

  • Update-Metadaten 24 Stunden gecacht → Cache leeren
  • 'upload' Plugins werden immer übersprungen
  • Versionsvergleich ist zeichenkettenbasiert
  • Anbieter hat Update möglicherweise noch nicht propagiert

„Uninstall failed"

  • Datei bereits manuell gelöscht
  • Datei vom Serverprozess gesperrt → Stoppen und erneut versuchen
  • Daemon-Verbindungsproblem

Plugin lässt Server nach Installation abstürzen

  1. Konsolenausgabe / Crash-Report prüfen
  2. Plugin deaktivieren (nicht löschen!) + neustarten zur Bestätigung
  3. Sind alle Abhängigkeiten installiert?
  4. Plugin-Kompatibilität mit MC-Version/Server-Software prüfen
  5. Eine ältere stabile Version versuchen
  6. Java-Version prüfen (17 für MC 1.18+, 21 für MC 1.21+)

„Cache clear failed"

  • Fehlerbenachrichtigung zeigt $e->getMessage()
  • SafeCacheService flush() konnte Schlüssel nicht entfernen
  • storage/framework/cache/ muss existieren und beschreibbar sein (0755)

„Cache health check failed"

  • Warnung vom PluginManager geloggt
  • Cache-Infrastruktur muss möglicherweise repariert werden
  • php artisan cache:clear als vollständiger Reset

Interne Provider-Funktionen (Referenz)

Dieser Abschnitt dokumentiert den internen PHP-Code für jede Provider-Integration, einschließlich API-Parameter, Antwort-Schemata, Rate-Limits und Verarbeitungslogik.

SpigotMC / Spiget Provider — Vollständige Referenz

API-Endpunkt-Parameter — GET /v2/search/resources/{query}

Parameter Typ Pflicht Standard Beschreibung
query string (Pfad) Ja Suchbegriff (URL-kodiert, im Pfad)
size int Nein 10 Ergebnisse pro Seite (max 100)
page int Nein 1 1-basierte Seitennummer
sort string Nein Sortierfeld, Präfix - für absteigend (z.B. -downloads)
fields string Nein Komma-getrennte Feldnamen zur Einschränkung

API-Endpunkt-Parameter — GET /v2/resources (Durchsuchen ohne Query)

Parameter Typ Pflicht Standard Beschreibung
size int Nein 10 Ergebnisse pro Seite
page int Nein 1 Seitennummer
sort string Nein -downloads Standard: nach meisten Downloads sortiert

Antwort-Schema — Suchergebnisse

Feld Typ Beschreibung
[].id int SpigotMC-Ressourcen-ID
[].name string Ressourcenname
[].tag string Kurzbeschreibung / Tagline
[].downloads int Gesamtzahl Downloads
[].rating.average float Durchschnittliche Bewertung (0–5)
[].icon.url string Relativer Icon-Pfad (Spiget-CDN voranstellen)
[].testedVersions string[] Als kompatibel gelistete MC-Versionen
[].premium bool True bei kostenpflichtiger Ressource
[].external bool True wenn außerhalb von SpigotMC gehostet
[].updateDate int Unix-Zeitstempel der letzten Aktualisierung
[].releaseDate int Unix-Zeitstempel der Erstveröffentlichung
Header X-Total int Gesamtanzahl passender Ressourcen (für Paginierung)

Rate-Limits

Stufe Limit Hinweise
Ohne Authentifizierung ~600 Anfragen/10 Min pro IP Spiget nutzt Sliding-Window
Bei Überschreitung HTTP 429 Kein Retry-After-Header, ~60s warten
// SpigotMC-Ressourcen durchsuchen — mit Gesamtanzahl aus Header
$response = Http::timeout($timeout)
    ->get("https://api.spiget.org/v2/search/resources/{$query}", [
        'size' => $perPage,
        'page' => $page,
        'sort' => '-downloads',
    ]);

// Gesamtanzahl steht im X-Total-Antwort-Header (nicht im JSON-Body!)
$total = (int) $response->header('X-Total');
// Antwortverarbeitung — wie Ressourcen in Plugin-Karten umgewandelt werden
$resources = $response->json();
$plugins = collect($resources)->map(function ($r) {
    return [
        'id'            => $r['id'],
        'name'          => $r['name'],
        'summary'       => $r['tag'] ?? '',
        'author'        => '', // Spiget braucht separaten /resources/{id}/author-Aufruf
        'downloads'     => $r['downloads'] ?? 0,
        'icon_url'      => !empty($r['icon']['url'])
            ? "https://www.spigotmc.org/{$r['icon']['url']}"
            : null,
        'updated_at'    => date('c', $r['updateDate'] ?? 0),
        'versions'      => $r['testedVersions'] ?? [],
        'provider'      => 'spiget',
        'has_direct_download' => !($r['premium'] ?? false) && !($r['external'] ?? false),
    ];
});
// Download-Verfügbarkeitsprüfung — HEAD-Anfrage vor dem Download-Versuch
$check = Http::head("https://api.spiget.org/v2/resources/{$id}/download");
if ($check->status() !== 200) {
    // Content-Type-Prüfung: JAR = direkter Download, HTML = Premium/extern
    $contentType = $check->header('Content-Type');
    if (str_contains($contentType, 'text/html')) {
        $plugin['has_direct_download'] = false;
        // Zeigt „Externe Ressource"- oder „Premium"-Badge
    }
}
// Versionsliste abrufen mit Sortierung nach Veröffentlichungsdatum
$versions = Http::timeout($timeout)
    ->get("https://api.spiget.org/v2/resources/{$id}/versions", [
        'size' => 20,
        'sort' => '-releaseDate',
    ])->json();

// Jede Version: { id, uuid, name, releaseDate, downloads, rating }
// Kein Datei-Hash über die Spiget-API verfügbar

Spiget-spezifisches Verhalten:

  • Ressourcen mit premium: true können nicht via API heruntergeladen werden — erfordert SpigotMC-Kauf
  • Externe Ressourcen (external: true) liegen außerhalb von SpigotMC — Link manuell folgen
  • Icons verwenden data/resource_icons/{id}/{id}.jpg-Format vom Spiget-CDN
  • Versionsfilterung prüft ob testedVersions die gewünschte MC-Version enthält
  • Keine Abhängigkeitsauflösung — die Spiget-API liefert keine Abhängigkeitsdaten
  • Autoreninfo benötigt separaten GET /resources/{id}/author-Aufruf — Plugin führt dies verzögert aus

CurseForge Provider (Plugins) — Vollständige Referenz

Verwendet die gleiche CurseForge-API wie Game Mods, aber mit classId=5 (Bukkit Plugins). Die classId ist der entscheidende Unterschied.

API-Endpunkt-Parameter — GET /v1/mods/search

Parameter Typ Pflicht Standard Beschreibung
gameId int Ja 432 Immer Minecraft für Plugins
classId int Ja 5 Bukkit Plugins (NICHT 9137, das sind Mods!)
searchFilter string Nein Volltextsuche
sortField int Nein 2 1=Featured (mit Query), 2=Beliebtheit (ohne)
sortOrder string Nein desc Sortierrichtung
gameVersion string Nein MC-Versionsfilter
pageSize int Nein 20 Max 50
index int Nein 0 Paginierungs-Offset

Antwort-Schema — Gleiche Struktur wie Game Mods CurseForge (siehe Game Mods-Dokumentation), wesentliche Unterschiede:

  • classId = 5 in allen Ergebnissen
  • categories[].classId entspricht Plugin-Kategorien, nicht Mod-Kategorien
  • latestFilesIndexes[] kann Bukkit/Spigot/Paper-Kompatibilitätsmarkierungen enthalten
// Plugin-Suche — classId=5 ist der entscheidende Unterschied zu Mods (9137)
$response = Http::withHeaders(['x-api-key' => $apiKey])
    ->timeout($timeout)
    ->get('https://api.curseforge.com/v1/mods/search', [
        'gameId'        => 432,     // Minecraft
        'classId'       => 5,       // ⚠ Bukkit Plugins — NICHT 9137 (Mods)!
        'searchFilter'  => $query,
        'sortField'     => $query ? 1 : 2,  // Dynamische Sortierung
        'sortOrder'     => 'desc',
        'gameVersion'   => $mcVersion,
        'pageSize'      => $perPage,
        'index'         => ($page - 1) * $perPage,
    ]);
// Antwortverarbeitung — gleiche Struktur wie Mods, classId unterscheidet sich
$results = $response->json('data', []);
$plugins = collect($results)->map(function ($mod) {
    return [
        'id'         => $mod['id'],
        'name'       => $mod['name'],
        'slug'       => $mod['slug'],
        'summary'    => $mod['summary'],
        'author'     => $mod['authors'][0]['name'] ?? 'Unbekannt',
        'downloads'  => $mod['downloadCount'],
        'icon_url'   => $mod['logo']['url'] ?? null,
        'provider'   => 'curseforge',
    ];
});
// Rekursive Abhängigkeitsauflösung — gleiches Muster wie bei Game Mods
foreach ($file['dependencies'] as $dep) {
    if ($dep['relationType'] === 3) {  // Benötigte Abhängigkeit
        $depPlugin = $this->fetchMod($dep['modId']);
        $this->installPlugin($depPlugin);  // Rekursiv
    }
}
// Beschreibungsanreicherung — CurseForge kann leere Zusammenfassung liefern
if (empty($mod['summary'])) {
    $html = Http::withHeaders(['x-api-key' => $apiKey])
        ->get("https://api.curseforge.com/v1/mods/{$mod['id']}/description")
        ->body();
    // HTML wird zu Klartext umgewandelt, max 200 Zeichen
}

CurseForge Plugin Provider-Fehlertabelle

Fehler / Log-Nachricht Ursache Auswirkung Lösung
classId=9137 Ergebnisse Code verwendet Mod-classId Falscher Inhaltstyp classId=5 für Plugins sicherstellen
Leere Beschreibung Plugin hat keine CurseForge-Zusammenfassung Fehlende Info Anreicherungs-API-Aufruf füllt dies
Abhängigkeitsschleife Zirkuläre relationType=3 Installation hängt Auf Plugin-Seite melden
downloadUrl null Autor hat Download eingeschränkt Manueller Download nötig Von CurseForge-Website herunterladen

Modrinth Provider (Plugins) — Vollständige Referenz

API-Endpunkt-Parameter — GET /v2/search

Parameter Typ Pflicht Standard Beschreibung
query string Nein Suchbegriffe
facets string (JSON) Ja siehe unten Muss project_type:plugin enthalten
limit int Nein 20 Max 100
offset int Nein 0 Paginierungs-Offset

Plugin-spezifische Facetten

// Das Plugin baut diese Facetten speziell für Server-Plugins
$facets = [
    ['project_type:plugin'],                         // Muss Plugin sein, nicht Mod
    ['categories:paper', 'categories:spigot',        // Serversoftware-Kompatibilität
     'categories:bukkit', 'categories:purpur'],       // ODER-verknüpft im inneren Array
];
if ($mcVersion) $facets[] = ["versions:$mcVersion"];
if ($loader)    $facets[] = ["categories:$loader"];  // z.B. categories:paper

$params['facets'] = json_encode($facets);

Antwort-Schema — Gleiche Struktur wie Game Mods Modrinth (siehe Game Mods-Dokumentation), wesentliche Unterschiede:

  • hits[].project_type = "plugin" (nicht "mod")
  • hits[].categories enthält Servertypen wie bukkit, spigot, paper, purpur
  • hits[].loaders listet unterstützte Serverplattformen
// Antwortverarbeitung — identisch zu Mods, project_type unterscheidet sich
$hits = $response->json('hits', []);
$plugins = collect($hits)->map(function ($hit) {
    return [
        'id'         => $hit['project_id'],
        'name'       => $hit['title'],
        'slug'       => $hit['slug'],
        'summary'    => $hit['description'],
        'author'     => $hit['author'],
        'downloads'  => $hit['downloads'],
        'icon_url'   => $hit['icon_url'] ?? null,
        'versions'   => $hit['versions'] ?? [],
        'provider'   => 'modrinth',
    ];
});

Modrinth Plugin Provider-Fehlertabelle

Fehler / Log-Nachricht Ursache Auswirkung Lösung
Keine Ergebnisse mit project_type:plugin Plugin nicht korrekt auf Modrinth getaggt Fehlende Plugins Bei anderen Providern suchen
SHA-1-Abweichung Download beschädigt Integritätsprüfung schlägt fehl Cache leeren, Download wiederholen
Falsche project_type-Ergebnisse Facetten falsch konfiguriert Mods mit Plugins vermischt project_type:plugin-Facette sicherstellen

PaperMC / Hangar Provider — Vollständige Referenz

API-Endpunkt-Parameter — GET /v1/projects

Parameter Typ Pflicht Standard Beschreibung
q string Nein Suchanfrage
limit int Nein 25 Ergebnisse pro Seite (max 25)
offset int Nein 0 Paginierungs-Offset
sort string Nein -stars Sortierung: stars, downloads, views, newest, updated, recent (Präfix - für abst.)

API-Endpunkt-Parameter — GET /v1/projects/{slug}/versions

Parameter Typ Pflicht Standard Beschreibung
slug string (Pfad) Ja Projekt-Slug (z.B. ViaVersion)
limit int Nein 10 Versionen pro Seite
offset int Nein 0 Paginierungs-Offset
platform string Nein Filter: PAPER, VELOCITY, WATERFALL

Antwort-Schema — Projektsuche

Feld Typ Beschreibung
result[].namespace.owner string Benutzername des Projektbesitzers
result[].namespace.slug string Projekt-URL-Slug
result[].name string Anzeigename
result[].description string Kurzbeschreibung
result[].stats.downloads int Gesamtdownloads
result[].stats.stars int Sternebewertungen
result[].stats.watchers int Beobachter
result[].avatarUrl string Projekt-Icon-URL
result[].lastUpdated string ISO 8601 Zeitstempel
pagination.count int Gesamtergebnisse
pagination.limit int Seitengröße
pagination.offset int Aktueller Offset

Antwort-Schema — Versionen

Feld Typ Beschreibung
result[].name string Versions-Anzeigename
result[].createdAt string ISO 8601 Veröffentlichungsdatum
result[].downloads.PAPER[].fileInfo.name string JAR-Dateiname
result[].downloads.PAPER[].fileInfo.sizeBytes int Dateigröße
result[].downloads.PAPER[].externalUrl string|null Externer Download-Link (falls extern gehostet)
result[].platformDependencies.PAPER string[] MC-Versionsbereich (z.B. ["1.8-1.21"])
result[].pluginDependencies.PAPER[].name string Namen benötigter Plugins
// Projektsuche — mit Paginierung
$response = Http::timeout($timeout)
    ->get('https://hangar.papermc.io/api/v1/projects', [
        'q'      => $query,
        'limit'  => $perPage,
        'offset' => ($page - 1) * $perPage,
    ]);

// Antwortverarbeitung
$results = $response->json('result', []);
$plugins = collect($results)->map(function ($project) {
    return [
        'id'         => $project['namespace']['slug'],  // owner/slug nicht nötig für Hangar
        'name'       => $project['name'],
        'summary'    => $project['description'],
        'author'     => $project['namespace']['owner'],
        'downloads'  => $project['stats']['downloads'] ?? 0,
        'icon_url'   => $project['avatarUrl'] ?? null,
        'updated_at' => $project['lastUpdated'],
        'provider'   => 'hangar',
    ];
});
// Versionsliste mit Plattform-Priorität
$versions = Http::timeout($timeout)
    ->get("https://hangar.papermc.io/api/v1/projects/{$slug}/versions", [
        'limit' => 20,
    ])->json('result', []);

// Plattform-Priorität: PAPER → VELOCITY → WATERFALL
// Jede Version hat platformDependencies mit MC-Versionsbereichen
foreach ($versions as $v) {
    $mcVersions = $v['platformDependencies']['PAPER'] ?? [];
    // Gibt z.B. ["1.8-1.21"] zurück — bedeutet 1.8 bis 1.21 unterstützt

    // Prüfung auf externe URL — manche Plugins verlinken zu GitHub/Jenkins
    if (!empty($v['downloads']['PAPER'][0]['externalUrl'])) {
        $plugin['requires_manual_download'] = true;
    }
}

Hangar-spezifisches Verhalten:

  • Version-agnostisch: Filtert NICHT nach spezifischer MC-Version — zeigt alle Versionen für alle Plattformen
  • Projekte verwenden namespace.owner/namespace.slug-Format (z.B. ViaVersion/ViaVersion)
  • externalUrl in Downloads → Plugin wird als requires_manual_download markiert
  • Statistiken umfassen downloads, stars, watchers — für Sortierungsranking verwendet
  • Plugin-Abhängigkeiten in pluginDependencies.PAPER[].name — nur informativ (nicht automatisch aufgelöst)
  • MC-Versionsfilter ist in der UI ausgeblendet für Hangar, da serverseitige Filterung nicht unterstützt wird

Hangar Provider-Fehlertabelle

Fehler / Log-Nachricht Ursache Auswirkung Lösung
Keine Ergebnisse Suchanfrage zu spezifisch oder keine Hangar-Plugins passen Leere Seite Kürzere Suchbegriffe verwenden
„Version nicht gefunden" Projekt von Hangar entfernt Download schlägt fehl Projekt wurde vom Autor entfernt
Falsche Plattform-Version Version für VELOCITY statt PAPER Inkompatible JAR platformDependencies vor Download prüfen
Externe URL-Weiterleitung Plugin auf GitHub/Jenkins gehostet Automatische Installation nicht möglich Manuell von externer URL herunterladen
CDN-Timeout Hangar-Download-Server langsam Download schlägt fehl Timeout erhöhen, später erneut versuchen

GeyserMC Provider — Vollständige Referenz

API-Endpunkt-Parameter — GET /v2/projects

Parameter Typ Pflicht Standard Beschreibung
(keine) Gibt alle Projektnamen zurück (immer 6)

API-Endpunkt-Parameter — GET /v2/projects/{project}/versions/latest/builds/latest

Parameter Typ Pflicht Standard Beschreibung
project string (Pfad) Ja Einer der 6 Projektnamen

Die 6 GeyserMC-Projekte

Projekt Beschreibung Primärer Download-Key
geyser Bedrock-zu-Java-Brücke spigot
floodgate Bedrock-Kontoverknüpfung spigot
hurricane Performance-Verbesserung spigot
geyserconnect Multi-Server-Verbinder standalone
thirdpartycosmetics Bedrock-Kosmetik-Unterstützung spigot
emoteoffhand Emote-Offhand-Fix spigot

Antwort-Schema — Neuestes Build

Feld Typ Beschreibung
build int Build-Nummer
version string Versionsstring (z.B. 2.4.0)
downloads.{platform}.name string JAR-Dateiname (z.B. Geyser-Spigot.jar)
downloads.{platform}.sha256 string SHA-256-Hash zur Integritätsprüfung
changes[].commit string Commit-Hash
changes[].summary string Commit-Nachricht
// Alle GeyserMC-Projekte auflisten (gibt immer die gleichen 6 zurück)
$projects = Http::timeout($timeout)
    ->get('https://download.geysermc.org/v2/projects')
    ->json();
// ["geyser","floodgate","hurricane","geyserconnect","thirdpartycosmetics","emoteoffhand"]
// Neuestes Build mit plattformspezifischen Downloads abrufen
$build = Http::timeout($timeout)
    ->get("https://download.geysermc.org/v2/projects/{$project}/versions/latest/builds/latest")
    ->json();

// Antwortverarbeitung — Versions-ID wird aus Version + Build zusammengesetzt
$versionId = $build['version'] . '-' . $build['build'];  // z.B. "2.4.0-670"

// Download-Key-Auflösung — Plattform hängt vom Projekt ab
$downloadKey = match ($project) {
    'geyserconnect' => 'standalone',
    default         => 'spigot',  // Paper/Spigot-Server verwenden 'spigot'-Key
};

$jarName  = $build['downloads'][$downloadKey]['name'];      // "Geyser-Spigot.jar"
$sha256   = $build['downloads'][$downloadKey]['sha256'];     // Integritäts-Hash
$url      = "https://download.geysermc.org/v2/projects/{$project}/versions/{$build['version']}/builds/{$build['build']}/downloads/{$downloadKey}";
// GeyserMC spezieller Download — umgeht pull(), nutzt cURL direkt
// Dies liegt daran, dass GeyserMC-URLs spezielle User-Agent-Behandlung erfordern
$tmpFile = tempnam(sys_get_temp_dir(), 'geyser_');
$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => false,
    CURLOPT_FILE           => fopen($tmpFile, 'w'),
    CURLOPT_TIMEOUT        => 60,
    CURLOPT_FOLLOWLOCATION => true,
]);
curl_exec($ch);
curl_close($ch);
// Datei wird dann via Daemon putContent() geschrieben
$this->fileRepository->putContent("/plugins/{$jarName}", file_get_contents($tmpFile));
unlink($tmpFile);

GeyserMC-spezifisches Verhalten:

  • Keine Suche — zeigt immer alle 6 Projekte in einer festen Liste
  • Version-agnostisch — zeigt immer das neueste Build, keine MC-Versionsfilterung
  • SHA-256-Prüfsummen für jeden Download verfügbar — zur Integritätsprüfung verwendet
  • Download-URLs: https://download.geysermc.org/v2/projects/{project}/versions/{ver}/builds/{build}/downloads/{platform}
  • Verfügbare Plattformen variieren je Projekt: spigot, bungee, standalone, velocity, fabric
  • 24-Stunden-Metadaten-Cache für Build-Informationen
  • Verwendet Base64-SVG-Insel-Icon für alle Projekte (fest kodiert, nicht aus der API)
  • Fest kodierte Download-Zahlen angezeigt (nicht live abgefragt)
  • MC-Versionsfilter ist in der UI ausgeblendet für GeyserMC (irrelevant)

GeyserMC Provider-Fehlertabelle

Fehler / Log-Nachricht Ursache Auswirkung Lösung
Nur 6 Projekte angezeigt Erwartet — GeyserMC hat genau 6 Kein Fehler Normaler Betrieb
„Build nicht gefunden" GeyserMC Build-Server-Problem Neueste Version nicht ermittelbar Später erneut versuchen, download.geysermc.org prüfen
Falsches Platform-JAR Falscher downloadKey gewählt Inkompatible JAR installiert spigot für Spigot/Paper-Server wählen
SHA-256-Abweichung Download bei Übertragung beschädigt Integritätsprüfung schlägt fehl Erneut herunterladen, Netzwerkstabilität prüfen
Alte Version installiert 24-Stunden-Metadaten-Cache Zeigt veraltetes Build Cache leeren für sofortige Update-Prüfung
cURL-Download fehlgeschlagen Temp-Datei-Schreibfehler oder Timeout Keine JAR heruntergeladen Temp-Verzeichnis-Schreibrechte prüfen, Timeout erhöhen
GeyserMC download failed: {message} Beliebiger Fehler in der Download-Pipeline Installation schlägt fehl Server-Logs auf spezifischen Fehler prüfen

Such-Wiederholungslogik

Wenn die initiale Suche mit Versionsfilter 0 Ergebnisse liefert, wiederholt das Plugin automatisch ohne Versionsfilter. Dies hilft wenn eine bestimmte MC-Version noch nicht beim Provider indiziert ist.

// Automatische Fallback-Suche — gilt für alle durchsuchbaren Provider
$results = $this->search($query, $mcVersion, $loader);
if (empty($results) && $mcVersion) {
    // Wiederholung ohne Versionsfilter — Version evtl. noch nicht indiziert
    $results = $this->search($query, null, $loader);
    // Benutzer sieht alle Versionen, kann Kompatibilität manuell prüfen
}

Providerübergreifende Muster

// Deaktivieren/Aktivieren — in -bak-Namen schreiben, dann Original löschen (Daemon-Kompatibilität)
// Nutzt 3 Schritte: Lesen → neuen Namen schreiben → alten löschen
// KEIN einfaches Umbenennen — Pterodactyl-Daemon unterstützt kein atomares Rename
$content = $this->fileRepository->getContent("/plugins/{$filename}");
$this->fileRepository->putContent("/plugins/{$filename}-bak", $content);
$this->fileRepository->delete("/plugins/{$filename}");
// Update-bei-Deaktivierung — merkt sich deaktivierten Zustand über Updates hinweg
$wasDisabled = $plugin->is_disabled;
$this->updatePlugin($plugin);  // Installiert neue Version
if ($wasDisabled) {
    $this->disablePlugin($plugin);  // Nach Update erneut deaktivieren
}

Vollständige Benachrichtigungs-Referenz

Ereignis Typ Titel Nachricht
Version erkannt Erfolg Erkennung „Minecraft-Version erkannt: X.X.X"
Version nicht erkannt Warnung Erkennung „Minecraft-Version konnte nicht erkannt werden"
Installation gestartet Info Installation „Plugin-Installation gestartet"
Installation erfolgreich Erfolg Installiert „Plugin erfolgreich installiert" (geloggt)
Installation fehlgeschlagen Fehler Fehler „Installation fehlgeschlagen" + Fehlerdetail
Abhängigkeiten Info Abhängigkeiten „X zusätzliche Plugins werden installiert…"
Plugin deaktiviert Erfolg Deaktiviert „Plugin deaktiviert: [Name]"
Plugin aktiviert Erfolg Aktiviert „Plugin aktiviert: [Name]"
Deaktivierung fehlgeschlagen Fehler Fehler „Deaktivierung fehlgeschlagen" + Fehler
Aktivierung fehlgeschlagen Fehler Fehler „Aktivierung fehlgeschlagen" + Fehler
Plugin deinstalliert Erfolg Entfernt „Plugin deinstalliert"
Deinstallation fehlgeschlagen Fehler Fehler Fehlerdetail
Cache geleert Erfolg Cache „Cache geleert" + Scan-Ergebnisse
Cache-Fehler Fehler Fehler „Fehler beim Cache leeren" + $e->getMessage()
ZIP gestartet Info Export „ZIP-Download gestartet"
ZIP fehlgeschlagen Fehler Export „ZIP-Download fehlgeschlagen"
CurseForge-Key fehlt Warnung Konfiguration „CurseForge API-Schlüssel nicht gesetzt"
Externe Ressource Warnung Download „Externe Ressource — manuell herunterladen"
Premium-Ressource Warnung Download „Premium-Ressource — Kauf erforderlich"
Dateiname nicht erkannt Warnung Installation „Dateiname konnte nicht ermittelt werden" (geloggt)
JAR-Metadaten-Fehler Warnung Installation „Plugin-Name konnte nicht aus JAR extrahiert werden" (geloggt)

HTTP-Fehlercode-Referenz (Alle Provider)

HTTP-Status Quelle Bedeutung Maßnahme
200 Alle Erfolg
400 CurseForge/Spiget Ungültige Anfrage Game-ID, Class-ID, Query-Format prüfen
401 CurseForge API-Key ungültig Key auf console.curseforge.com erneuern
403 CurseForge Fehlende Berechtigungen Key neu generieren
403 Plugin Feature-Flag plugins fehlt ["plugins"] zu Egg-Features hinzufügen
404 Alle Provider Ressource nicht gefunden ID/Slug prüfen oder Ressource wurde entfernt
404 Spiget Version nicht gefunden Ressource wurde möglicherweise vom Autor gelöscht
429 CurseForge Rate-Limit 60s warten, Cache-Dauer erhöhen
429 Spiget Rate-Limit Häufigkeit reduzieren, 60s warten
500 Alle Serverfehler Später erneut versuchen
502/503 Alle Gateway/Wartung Provider offline
0 / Timeout Alle Verbindungs-Timeout MODS_REQUEST_TIMEOUT erhöhen, DNS/Firewall prüfen

Provider-spezifische Fehlertabelle

SpigotMC / Spiget Fehler

Fehler / Symptom Ursache Lösung
Kein Download-Button Premium-Ressource Zuerst auf SpigotMC-Website kaufen
„Externe Ressource"-Label Plugin extern gehostet Link zur externen Seite folgen
Keine Versionen aufgelistet Sehr alte/inaktive Ressource Manuellen Upload im Dateimanager nutzen
Langsame Suche Spiget-API unter Last Timeout erhöhen, erneut versuchen
Fehlendes Icon Kein Icon für Ressource hochgeladen Kosmetisch — Plugin funktioniert einwandfrei
HEAD-Prüfung schlägt fehl Spiget-CDN-Timeout Erneut versuchen, Verbindung prüfen

Hangar Fehler

Fehler / Symptom Ursache Lösung
Keine Ergebnisse Suchanfrage zu spezifisch Kürzere/breitere Begriffe verwenden
„Version nicht gefunden" Hangar-Projekt entfernt Projekt wurde möglicherweise ausgelistet
Falsche Plattform Version für falschen Servertyp platformDependencies prüfen (PAPER vs WATERFALL)
Download fehlgeschlagen CDN-Timeout Erneut versuchen, Timeout erhöhen
Leere Statistiken Neues Projekt Noch keine Downloads erfasst

GeyserMC Fehler

Fehler / Symptom Ursache Lösung
Nur 6 Projekte angezeigt Erwartet — GeyserMC hat genau 6 Kein Fehler
„Build nicht gefunden" GeyserMC Build-Server-Problem Später erneut versuchen
Falsches Platform-JAR Falsche Download-Plattform gewählt spigot für Spigot/Paper-Server wählen
SHA-256-Abweichung Download beschädigt Erneut herunterladen, Verbindung prüfen
Alte Version installiert Versions-Cache beträgt 24h Cache leeren für sofortige Update-Prüfung