Veröffentlicht: August 9, 2026

Wer meinen letzten Post über den Broken Map Marker gelesen hat, weiß schon worum es geht: CS:S-Maps mit fehlenden Texturen sind nervig, und das Plugin hilft dabei, sie schnell zu markieren und aus dem Rotation zu schmeißen. Was ich da aber noch nicht hatte: eine automatische Möglichkeit, diese Maps auch wieder zu reparieren. Das ist jetzt der nächste Schritt.

map_fixer.py ist ein Python3-Script, das ich für meinen GunGame-Server geschrieben hab. Es läuft vier Mal täglich als Cron-Job, durchsucht die SRCDS-Console-Logs nach fehlenden Ressourcen-Fehlern, sucht auf GameBanana nach besseren Versionen der betroffenen Maps, lädt sie herunter, entpackt die Ressourcen in die richtigen Verzeichnisse und synchronisiert sie anschließend zu den FastDL-Servern. Alles automatisch, alles ohne manuelle Eingriffe.

Was das Script tatsächlich tut

SRCDS schreibt im Console-Log sehr deutlich welche Materials fehlen:

SRCDS Console Log — Missing Materials

Counter-Strike: Source schreibt beim Kartenwechsel in die Server-Console welche Texturen und Materialien beim Laden nicht gefunden wurden. Diese Einträge landen in der LGSM Console-Log-Datei. Das Script liest diese Datei aus und ordnet Fehler dem jeweiligen Kartennamen zu.

Missing map material: LOSTCOAST/MONASTERY/MONASTERY_WALL002C
Missing map material: COLOR/KHAKI
Missing map material: CUSTOM/GRASS1

Auf meinem Server hatte ich zum Beispiel gg_3tier mit 457 solcher Fehler und gg_aim_ag_texture5 mit über 1600. Das Script findet diese Maps automatisch und meldet sie — man muss nur noch sm_brokenmap mapname auf dem Server eingeben um sie in die Broken-Liste zu setzen. Den Fix übernimmt dann das Script beim nächsten Lauf.

Die vier Befehle

BefehlWas es tut
python3 map_fixer.py scanSRCDS-Logs nach fehlenden Ressourcen durchsuchen, Maps mit Fehlern ausgeben
python3 map_fixer.py listAlle Maps aus broken_maps.txt mit lokalem BSP-Status anzeigen
python3 map_fixer.py check [map]GameBanana und eigene Quellen nach Download-Paketen durchsuchen
python3 map_fixer.py fix [map]Download + Entpacken + FDL-Sync ausführen
python3 map_fixer.py fdl-syncAlle Spielressourcen komplett zu FastDL-Servern synchronisieren

Alle Befehle unterstützen --dry-run (nur simulieren, nichts schreiben) und --verbose für ausführlichere Ausgabe.

Installation

  1. pip3 install requests
  2. Script nach /opt/map_fixer.py (oder irgendwo anders)
  3. Beim ersten Start wird map_fixer.json automatisch mit dokumentierten Defaults angelegt
  4. Config anpassen (Pfade, FDL-Server, etc.)
  5. Testen: python3 map_fixer.py list --dry-run

Konfiguration (map_fixer.json)

Beim ersten Start legt das Script eine map_fixer.json an. Die wichtigsten Einstellungen:

map_fixer.json — Konfiguration

Die Konfigurationsdatei wird beim ersten Start automatisch angelegt. Alle Pfade sind für eine typische LGSM-Installation auf Linux vorbelegt. Anpassen muss man im Wesentlichen nur die fdl_servers-Liste und optional die custom_urls.

{
  "broken_maps_file": "/home/ggserver/serverfiles/cstrike/addons/sourcemod/configs/broken_maps.txt",
  "maps_dir":         "/home/ggserver/serverfiles/cstrike/maps",
  "game_dir":         "/home/ggserver/serverfiles/cstrike",
  "srcds_log_dir":    "/home/ggserver/log/console",
  "download_tmp":     "/tmp/map_fixer",

  "fdl_servers": [{
    "name": "fdl2.wonx.eu",
    "host": "192.168.10.20",
    "user": "root",
    "path": "/home/fdl2/htdocs/fdl2.wonx.eu/cstrike",
    "ssh_key": null
  }],

  "sources": {
    "gamebanana": { "enabled": true, "game_id": 27, "max_results": 5 },
    "custom_urls": [
      {"url": "https://meine-domain.de/maps/{map}.zip", "enabled": false}
    ]
  },

  "auto_mark_fixed": false,
  "dry_run": false
}

Der Parameter game_id: 27 ist die GameBanana-ID für Counter-Strike: Source. Das Script sucht dort automatisch nach dem Mapnamen und lädt das größte gefundene Archiv herunter, das zum Suchergebnis passt.

Mit auto_mark_fixed: true wird eine Map nach erfolgreichem Fix automatisch aus der broken_maps.txt entfernt — ohne dass man !unbrokenmap auf dem Server eingeben muss. Ich hab das bewusst auf false gelassen, damit man den Fix erst kurz ingame prüfen kann.

Cron — 4x täglich automatisch

Der Cron auf meinem Server läuft um 04:00, 10:00, 16:00 und 22:00 Uhr:

crontab — Zeitgesteuerter Taskplaner auf Linux

Cron ist ein Dienst auf Linux-Systemen der Befehle zu bestimmten Zeiten ausführt. Die Konfiguration erfolgt über crontab -e. Das Format ist: Minute Stunde Tag Monat Wochentag Befehl. 0 4,10,16,22 * * * bedeutet: „Um 4, 10, 16 und 22 Uhr, jeden Tag“.

# In crontab -e eintragen:
0 4,10,16,22 * * * python3 /opt/map_fixer.py scan --config /opt/map_fixer.json >> /var/log/map_fixer.log 2>&1 && python3 /opt/map_fixer.py fix --config /opt/map_fixer.json >> /var/log/map_fixer.log 2>&1

Der Scan-Befehl läuft zuerst (und gibt aus welche Maps Probleme haben), danach versucht Fix die Maps in der broken_maps.txt zu reparieren. Das Log landet in /var/log/map_fixer.log.

Der Fix-Prozess im Detail

Was passiert wenn das Script eine Map fixen will:

  1. GameBanana-Suche nach dem Mapnamen (Game-Filter: CS:S, game_id 27)
  2. Name-Matching: Es werden nur Ergebnisse verwendet bei denen der Suchbegriff im Ergebnisnamen vorkommt — verhindert falsche Downloads
  3. Download des größten gefundenen Archivs (mehr Inhalt = mehr Ressourcen)
  4. Extraktion: Nur maps/, materials/, models/, sound/, resource/ werden entpackt — kein Path-Traversal möglich, keine anderen Dateipfade werden angefasst
  5. Ersetzen: Lokale Dateien werden nur ersetzt wenn die neue Version größer oder neuer ist
  6. FDL-Sync: rsync schiebt die geänderten Dateien zu den FastDL-Servern
  7. Feedback: Das Script meldet wieviele Dateien hinzugefügt und aktualisiert wurden

Wenn alles geklappt hat, kommt die Meldung:

Resources updated. Verify in-game, then run: sm_unbrokenmap gg_mapname

Eigene Download-Quellen

Neben GameBanana kann man eigene URL-Muster in der Config hinterlegen. Der Platzhalter {map} wird durch den Mapnamen ersetzt:

"custom_urls": [
  {"url": "https://mein-server.de/css-maps/{map}.zip", "enabled": true},
  {"url": "https://anderer-server.de/maps/{map}.bz2", "enabled": true}
]

Das Script prüft mit einem HTTP HEAD-Request ob die URL existiert (Status 200) und lädt sie dann erst herunter. Für die eigenen FDL-Server kann man so auch direkt die Quell-Server anderer Communities abfragen.

Download

  • map_fixer.py — Python3-Script (benötigt: pip3 install requests)

Das Script funktioniert mit jeder CS:S LGSM-Installation, die SourceMod verwendet. Die Pfade in der Config müssen auf die eigene Server-Struktur angepasst werden — beim ersten Start wird dafür eine fertige Config mit allen Optionen angelegt.

Beide Tools zusammen

Der Workflow mit beiden Scripts zusammen:

  1. Admin sieht eine Map mit fehlenden Texturen → !bm im Chat → Map ist in der Broken-Liste
  2. map_fixer.py läuft beim nächsten Cron-Lauf → sucht GameBanana nach einem besseren Download → lädt herunter → entpackt → FDL-Sync
  3. Admin prüft die Map kurz ingame → !unbrokenmap → Map ist wieder in der Rotation

Das geht natürlich auch ohne den manuellen Schritt — mit auto_mark_fixed: true läuft das komplett automatisch.