Files
fuesse-sexy/README.md
Guido 5018ab753a Admin-Panel (/admin): Auth, Spieler-Tracking, Live-Tuning, Bild-Verwaltung
- Passwortgeschütztes Panel unter /admin (Auto-Passwort 20 Zeichen, per CLI abrufbar:
  `node server/admin.js password` / `password reset`), In-Memory-Sessions + Cookie,
  Login-Rate-Limit.
- Spieler-Tracking: pro Score IP (CF/XFF/req.ip), Gerät/Browser (ua-parser-js),
  grober Ort (geoip-lite, offline) -> data/players.json; Aggregation pro Name.
- Live-Tuning: configStore (data/config.json) für Timer + Schwierigkeitskurve; Server
  (makeRound) und Client (/api/config) lesen daraus -> Änderungen ohne Neustart.
- Bild-Verwaltung: Upload/Löschen von Füßen & Deko (multer) + rescanLibrary().
- Panel-Aktionen: Spieler bannen/entbannen, Rangliste heute/alles leeren.
- Fix: .item object-fit:contain -> nicht-quadratische Bilder werden nicht mehr verzerrt.
- trust proxy für korrekte Client-IP hinter Reverse-Proxy/Cloudflare.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-05 22:19:52 +02:00

5.8 KiB
Raw Blame History

fuesse.sexy — „Wanted!" 🦶

Ein kleines Arcade-Spiel nach dem Vorbild des „Wanted!"-Minispiels aus New Super Mario Bros.: Oben ein Fahndungsplakat mit einem gesuchten Fuß, unten wuseln viele Füße (in verschiedenen Farben) + etwas Deko herum. Schnapp dir den gesuchten Fuß, bevor die Zeit abläuft — dann kommt sofort ein neues Plakat mit einer anderen Farbe.

  • Zeitdruck: Countdown; jeder Treffer gibt Zeit dazu, Fehlklick zieht Zeit ab. Bei 0 → Game-Over.
  • Wird schwerer: erst ordentliches Raster, dann wild verteilt, dann Bewegung (erst in 23 Gruppen, später einzeln) — und je weiter, desto schneller und mehr Füße.
  • Gesucht ist immer ein Fuß, aber die Farbe wechselt jede Runde — nicht auf Autopilot klicken!
  • Rangliste: die Top 10 auf der Startseite, serverseitig gespeichert. Nach dem Spiel wird einmal nach dem Namen gefragt (danach gecacht).

Installation

./install.sh

Das Skript installiert alles Nötige, startet den Server im Hintergrund und zeigt die URL. Dann im Browser öffnen: http://:3000 (lokal: http://localhost:3000).

Manuell: npm install && npm start.

Die Füße & Deko erweitern

Alle Bildchen liegen in library/:

library/
  feet/    ← die Füße (= die gesuchten Figuren). Farbe = Dateiname.
  props/   ← Deko ("andere Bildchen") als Zusatz-Ablenker.

Neue Bildchen einfach in den passenden Ordner legen und Server neu starten — fertig. Formate: .svg, .png, .webp, .jpg. Für Füße gilt: mind. 2 in library/feet/ (mehr = mehr Farb-Vielfalt). Am besten freigestellt (transparenter Hintergrund), grob quadratisch.

Woher Bildchen nehmen?

openclipart.org (CC0), svgrepo.com (CC0-Filter), kenney.nl (CC0), pixabay.com. Bei Flaticon/Freepik Namensnennung beachten.

Feintuning

In public/js/app.js oben:

  • START_TIME, MAX_TIME, BONUS, PENALTY — Timer/Balance.
  • difficulty(score) — Anzahl, Bewegungs-Stufen (grid/scatter/groups/individual) und Tempo je Score.

Rangliste

  • Zwei Boards: Hall of Fame (Allzeit-Top-5) + Heute (Top-10). Gespeichert in data/leaderboard.json (wird automatisch angelegt, überlebt Neustarts).
  • Anti-Cheat: server-autoritative Runden. Der Server bestimmt pro Runde das Ziel und alle Items (mit zufälligen IDs) und validiert jeden Treffer gegen die Ziel-ID der aktuellen Runde (/api/game/hit mit nonce + itemId). Blindes „Treffer-Spam" bringt dadurch nichts mehr; zusätzlich Reaktionszeit-Untergrenze, Mindestabstand und Deckelung nach echter Spielzeit. Beim Eintragen (/api/score) zählt nur die server-gezählte Trefferzahl. Namen werden beim Anzeigen escaped (kein XSS).

    Hinweis: In einem Browserspiel bekommt der Client zwangsläufig die Renderdaten — ein eigens gebauter Solver-Bot bleibt theoretisch möglich, 100 % dicht geht nicht.

Verwaltung per CLI

Auf dem Server (im Projektordner):

# Rangliste
node server/admin.js list                 # beide Boards anzeigen
node server/admin.js delete "Name"        # einen bestimmten Spieler löschen
node server/admin.js clear-today          # nur die heutige Rangliste leeren
node server/admin.js clear-all            # komplette Rangliste leeren

# Bannen (namensbasiert, case-insensitiv)
node server/admin.js ban "Name"           # sperren (+ vorhandene Einträge entfernen)
node server/admin.js unban "Name"         # Sperre aufheben
node server/admin.js bans                 # gebannte Namen anzeigen

# Betriebsmodus (wirkt SOFORT, ohne Neustart)
node server/admin.js mode                  # aktuellen Modus anzeigen
node server/admin.js mode public           # Spiel öffentlich unter "/"
node server/admin.js mode private geheim   # "/" gesperrt, Spiel nur unter "/geheim"

# Admin-Panel-Passwort
node server/admin.js password              # Passwort anzeigen (Login unter /admin)
node server/admin.js password reset        # neues Passwort erzeugen

(Kurzform via npm: npm run lb -- <befehl>.)

  • public (Default): / ist das Spiel.
  • private: / zeigt „You are not allowed to play", das Spiel läuft nur unter dem gewählten Pfad (/<pfad>) — praktisch zum Testen im Live-Betrieb.

Admin-Panel (/admin)

Passwortgeschütztes Web-Panel. Passwort wird beim ersten Start automatisch generiert (20 Zeichen) und liegt in data/admin.json — anzeigen mit node server/admin.js password.

Funktionen:

  • Spieler: approximative Zuordnung (IP, grober Ort via geoip-lite offline, Gerät, Browser) aus den Spiel-Logs; einzelne Spieler direkt bannen/entbannen.
  • Einstellungen: Timer (Start/Max/Bonus/Strafe) und Schwierigkeitskurve (Objekt-Anzahl, Stufen, Tempo) live einstellen — wirkt sofort beim nächsten Spielstart.
  • Bilder: Füße & Deko hochladen/löschen (kein Neustart). Empfehlung: quadratische Bilder, 256×256 oder 512×512 PNG (transparent) bzw. SVG mit quadratischem viewBox; nicht-quadratische werden per object-fit: contain eingepasst statt verzerrt.
  • Rangliste: heute/alles zurücksetzen.

Datenschutz: IP + grober Ort + Gerät/Browser sind personenbezogen (nur für Moderation). Für den öffentlichen Betrieb einen kurzen Datenschutz-Hinweis ergänzen.

Deployment (Ausblick)

Normaler Node-Server. Auf einen Node-Host bringen (VPS/LXC/Railway/Render), ./install.sh, Domain fuesse.sexy per Reverse-Proxy (z.B. Nginx Proxy Manager) darauf zeigen. Für HTTPS hinter Cloudflare: DNS-Challenge (Cloudflare-Token) im Proxy nutzen.

Projektstruktur

server/index.js   schlanker Express-Server (Bildchen-Liste + Rangliste)
public/           Frontend (Startseite, Spiel, Game-Over) — Vanilla JS
library/feet/     die Füße (gesuchte Figuren)
library/props/    Deko-Ablenker
data/             Rangliste (leaderboard.json, zur Laufzeit)
install.sh        Ein-Befehl-Setup + detached Start