aether-framework/README.md
Jerrit Fritzsche e4b82dd685 Aether-Framework: Fachmodule, Admin-Panel und Docker-Datenbank
- aether-medical: Stationen/Belegung, Intensivstation, Blutbank, Fuhrpark,
  Nachrichten/Aushänge, Berichte und Textbausteine (server + NUI)
- aether-admin: vollständiges Server-Admin-Panel als echtes FiveM-Resource,
  an aether-core gekoppelt (Rechte über aether_users.admin_group), mit
  WebRTC-Live-Kameras (Bildschirmfreigabe) und separatem Media-Server (SFU)
- Prototypen admin/ vervollständigt
- SQL-Schema aether_admin.sql
- Docker-Compose mit MariaDB und idempotenter Auto-Migration (schema_migrations)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 18:55:32 +02:00

683 lines
37 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Aether Framework
Deutschsprachiges FiveM GTA-RP-Framework (in Entwicklung).
Das Projekt besteht aus zwei Teilen:
1. **Lauffähiger FiveM-Server** (`server.cfg`, `resources/[aether]/`) — im Aufbau
2. **UI-Prototypen** (die restlichen Ordner) — reine HTML-Entwürfe, die modulweise
in echte Resources überführt werden
---
## Server einrichten
**Voraussetzungen:** FiveM-Server-Artifacts, MySQL/MariaDB, ein Lizenzschlüssel von
[keymaster.fivem.net](https://keymaster.fivem.net).
1. **Datenbank anlegen** — Schema einspielen:
```bash
mysql -u root -p < sql/aether.sql
```
2. **oxmysql herunterladen** (nicht in diesem Repo enthalten) von
[github.com/overextended/oxmysql](https://github.com/overextended/oxmysql/releases)
und nach `resources/[standalone]/oxmysql/` entpacken.
3. **`server.cfg` anpassen** — Lizenzschlüssel und `mysql_connection_string` eintragen.
4. **Server starten:**
```bash
./run.sh +exec server.cfg # Linux
FXServer.exe +exec server.cfg # Windows
```
### Aufbau
| Pfad | Inhalt |
|---|---|
| `server.cfg` | Serverkonfiguration, Startreihenfolge der Ressourcen |
| `sql/aether.sql` | Datenbankschema (Benutzer, Charaktere, Inventar, Fahrzeuge, Transaktionen) |
| `resources/[aether]/aether-core/` | **Fundament**: Spielerverwaltung, Charaktere, Geld, Zustand, NUI-Helfer |
| `resources/[aether]/aether-loading/` | Ladebildschirm (migriert) |
### aether-core
Das Fundament, von dem alle Module abhängen. Es übernimmt:
- **Verbindungsaufbau** mit Bannprüfung und Benutzeranlage (erkannt an der Rockstar-Lizenz)
- **Charakterverwaltung** (Multicharacter vorbereitet; legt vorerst automatisch einen
Startcharakter an, bis `aether-character` migriert ist)
- **Spawn** an der zuletzt gespeicherten Position, Ped-Modell nach Geschlecht
- **Geld** (Bargeld / Konto / Schwarzgeld) inkl. Deckungsprüfung und Transaktionsprotokoll
- **Zustand** (Leben, Hunger, Durst, Ausdauer) mit langsamem Verbrauch und Schaden bei Leere
- **Automatisches Speichern** alle 5 Minuten sowie bei Disconnect und Ressourcen-Stopp
- **NUI-Helfer**, damit Module Oberflächen einheitlich öffnen/schließen
**Schnittstelle für andere Module (Exports):**
```lua
-- Serverseite
local spieler = exports['aether-core']:HoleSpieler(source)
exports['aether-core']:FuegeGeldHinzu(source, 'bargeld', 500, 'Lohn')
exports['aether-core']:EntferneGeld(source, 'konto', 250, 'Einkauf')
-- Clientseite
local daten = exports['aether-core']:HoleSpielerDaten()
exports['aether-core']:OeffneNui('aether-phone', { aktion = 'oeffnen' })
exports['aether-core']:SchliesseNui()
```
Konfiguration liegt zentral in `aether-core/shared/config.lua` (Spawnpunkt, Startgeld,
Verbrauchsraten, Speicherintervall, Rechtegruppen).
---
## Systeme
### 🖥️ Ladebildschirm (`resources/[aether]/aether-loading/`) ✅ migriert
Bereits als FiveM-Ressource eingebunden (`loadscreen`). Bleibt sichtbar, bis der Core den
Charakter gespawnt hat (`loadscreen_manual_shutdown`).
Zum Ansehen im Browser: `resources/[aether]/aether-loading/html/index.html`.
**Enthaltene Elemente:**
- **Animierter Hintergrund**: Aurora-Verlauf + aufsteigende Partikel (Canvas)
- **Aether-Branding** mit Titel und Server-Statistiken (Spieler online/max, Voice, Discord)
- **Fortschrittsbalken** mit Prozentanzeige und wechselndem Status („Lade Ressource …"),
am Ende **„Bereit"-Zustand**
- **Info-Karussell**: News, Serverregeln und Spieltipps im automatischen Wechsel (klickbare Punkte)
- **Musik-Player**: sanftes Ambient-Pad per **WebAudio** erzeugt (kein externes Audio),
Play/Pause, nächster Titel, Lautstärke
> Der Fortschritt ist hier simuliert — in FiveM von echten Lade-Events getrieben. Server-Daten
> (`server`), Karussell-Inhalte (`karussell`) und Playlist (`playlist`) sind vom UI getrennt.
### ❤️ HUD (`resources/[aether]/aether-hud/`) ✅ migriert
Läuft als dauerhaftes Overlay im Spiel. Die Werte kommen aus dem Core und vom Fahrzeug —
es wird nur gesendet, wenn sich tatsächlich etwas geändert hat.
**Datenquellen:**
- **Geld** aus `aether:client:geldGeaendert` (Schwarzgeld erscheint nur, wenn vorhanden)
- **Hunger/Durst** aus `aether:client:zustandGeaendert` (Core-Verbrauchsschleife)
- **Leben** aus `GetEntityHealth` (GTA zählt ab 100 → wird in 0–100 % umgerechnet)
- **Ausdauer** aus dem Sprint-Vorrat des Spielers
- **Voice** aus dem eingebauten Mumble (`NetworkIsPlayerTalking`, Reichweite → Flüstern/Normal/Rufen)
- **Fahrzeug** (`client/fahrzeug.lua`): Tempo, Tank, Motor sowie ein **Sicherheitsgurt** als
Skriptmechanik — Taste `B`, verhindert bei angelegtem Gurt das Herausschleudern
**Export für andere Module:**
```lua
exports['aether-hud']:SetzeSichtbar(false) -- HUD ausblenden, z. B. bei offenen Menüs
```
> **Browser-Fallback:** Ohne FiveM blendet die Seite Kulisse und **Demo-Panel** wieder ein und
> lässt die Verbrauchssimulation laufen — weiterhin eigenständig ansehbar unter
> `resources/[aether]/aether-hud/html/index.html`.
**Anzeigen:**
- **Statusringe**: Leben, Hunger, Durst, Ausdauer (SVG-Ringe mit Zahl)
- **Voice-Anzeige** mit Reichweite (Flüstern/Normal/Rufen) und Sprech-Indikator
- **Geld**: Bargeld, Konto und optional **Schwarzgeld** (blinkt bei Änderung)
- **Fahrzeug-HUD**: Tacho (270°-Bogen), Gang, Tankanzeige, Warnleuchten für Gurt & Motor
**Simulation (Prototyp):**
- Hunger/Durst sinken langsam; leerer Magen/Durst zieht am Leben; Tank sinkt bei Fahrt
- Schaden geht auf das Leben; Aktionen wie Essen/Trinken/Heilen
- Fahrzeug-Modus mit Tempo-/Tank-Slider, Gurt- und Motor-Umschaltung
> Der komplette Zustand liegt getrennt im `hud`-Objekt (Status, Geld, Fahrzeugwerte). In FiveM
> per NUI vom Client gesetzt; das Demo-Panel entfällt dort. Geld-/Voice-Konzepte passen zu
> `bank/` und dem Voice-System.
### 💀 Tod / Respawn (`resources/[aether]/aether-death/`) ✅ migriert
Löst automatisch aus, sobald die Lebensenergie fällt. Der Spieler geht zu Boden statt zu
sterben — GTAs eigener Respawn wird unterbunden.
**Server führt den Countdown:** Verblutungszeit (5:00) und Respawn-Sperre (45 s) laufen
serverseitig. Der Client zeigt sie nur an und kann sie nicht beschleunigen.
**Ablauf:**
- **Rettungsdienst rufen** → löst `aether:death:notruf` aus; ein Rettungsdienst-Modul kann
daraus einen Einsatz erzeugen. Die Position wird aktuell gehalten (man kann kriechen)
- **Um Hilfe rufen** → hörbarer Schmerzlaut für Umstehende
- **Aufgeben** erst nach Ablauf der Sperre; danach Aufwachen im **nächstgelegenen Krankenhaus**
(drei Standorte) gegen **Behandlungspauschale** (erst Bargeld, dann Konto)
- **Verbluten** führt zum selben Ergebnis
- **Wiederbelebung** durch den Rettungsdienst über einen Export — mit Entfernungsprüfung
**Exports für den Rettungsdienst:**
```lua
exports['aether-death']:Wiederbeleben(quelle, helferQuelle) -- prüft die Entfernung
exports['aether-death']:IstVerletzt(source)
exports['aether-death']:HoleVerletzte() -- für eine Einsatzkarte
```
**Verwundet-Zustand:**
- **Verblutungs-Countdown** (5:00) mit animierter **EKG-Linie**, deren Herzschlag mit der
Restzeit langsamer wird; pulsierende blutrote Vignette (bei < 60 s „kritisch")
- **Rettungsdienst rufen** → Notruf mit zufälliger **Eintreff-ETA**, danach Behandlung → wiederbelebt
- **Um Hilfe rufen** (Ruf an Umstehende), **Aufgeben** erst nach **Respawn-Sperre** (45 s)
**Folgezustände:**
- **Behandelt** — rechtzeitig vom Sanitäter wiederbelebt (Leben 100 %)
- **Krankenhaus** — nach Aufgeben oder Verbluten; **Behandlungspauschale** als EMS-Rechnung
> Zustand liegt getrennt im `tod`-Objekt (Phase, Countdowns, EMS-Status). Der Notruf koppelt
> konzeptionell an den **Dispatch/EMS-Teil** von `faction/`, die Behandlungskosten an dessen
> **EMS-Finanzen**. In FiveM per NUI von echten Lebens-Events getrieben.
### 🎯 Radial-Menü (`radial/`)
Web-Prototyp des **kreisförmigen Interaktionsmenüs** — reines HTML/CSS/JS.
Zum Ansehen `radial/index.html` im Browser öffnen. **Taste `G`** öffnet/schließt das Rad, `Esc` schließt.
**Funktionen:**
- **SVG-Kuchenrad** mit farbigen Kategorie-Segmenten, Hover-Highlight und zentraler **Nabe**,
die das überfahrene Segment anzeigt
- **Untermenüs** (▸): Interaktion (Hände hoch, Ausweis zeigen …), Fahrzeug (Ab-/Aufschließen,
Motor, Kofferraum …), Emotes, Job, Notdienst — **Nabe = Zurück**
- **Direktaktionen**: Inventar, Handy (öffnen)
- Auswahl bestätigt per **Toast** und schließt das Rad; abdunkelnder Hintergrund bei geöffnetem Menü
> Menüstruktur liegt getrennt in `menue` (Kategorien mit `kinder`/`aktion`), Rad-Geometrie
> parametrisch (Segmentzahl beliebig). Aktionen sind kosmetisch — in FiveM NUI-Callbacks, die
> auf `inventory/`, `phone/`, `documents/`, `jobs/` und den Dispatch von `faction/` verweisen.
### ⛽ Aether Fuel — Tankstelle (`fuel/`)
Web-Prototyp der **Zapfsäulen-Oberfläche** — reines HTML/CSS/JS.
Zum Ansehen `fuel/index.html` im Browser öffnen. Ein **Demo-Panel** leert den Tank / füllt Geld auf.
**Funktionen:**
- **Digitale Zähler** (Liter + Preis) und **Tankanzeige** (E → F) mit Live-Zapf-Animation
- **Fahrzeugkarte** (Modell, Kennzeichen, Tankgröße) und **Spritsorten** mit Literpreis
(Benzin E10, Super Plus, Diesel)
- **Drei Tankmodi**: Volltanken, nach **Litern**, nach **Betrag (€)** — Zielmenge automatisch durch
Tankgröße **und** Guthaben begrenzt
- **Zahlung** per Bargeld oder Karte (Deckungsprüfung), **Stopp** mitten im Vorgang möglich
- **Kassenbeleg** nach dem Tanken; Geld und Füllstand werden aktualisiert
> Zustand getrennt: `spieler` (Geld), `fahrzeug` (Tank in Litern), `spritSorten` (Preise). Der
> Tank-Füllstand passt konzeptionell zum Tank-Wert im **Fahrzeug-HUD** (`hud/`); Geld später an
> `bank/` koppeln.
### 🕹️ Minispiele (`minigames/`)
Web-Prototyp einer **Skill-Check-Sammlung** — reines HTML/CSS/JS.
Zum Ansehen `minigames/index.html` im Browser öffnen. Übersicht + Nav wie beim Casino.
**Enthaltene Minispiele (je mit Erfolg/Fehlschlag-Ausgang):**
- **🎯 Skill-Check** — rotierenden Zeiger in der grünen Zone stoppen; mehrere Runden, wird
schneller und enger (Leertaste/Klick)
- **🔓 Lockpick** — Marker je Pin in der Zone treffen; 4 Pins, 3 Versuche, Zone schrumpft
- **🧠 Memory** — wachsende Feld-Sequenz merken und fehlerfrei wiederholen (Simon-artig)
- **🔢 Code knacken** — 4-stelligen Code per Deduktion (🟩 richtige Stelle / 🟨 richtige Ziffer)
gegen Zeit und begrenzte Versuche erraten
> Gemeinsame Shell mit Timer-Verwaltung (`stopAlle`) und Ergebnis-Banner (`spielEnde`). In FiveM
> per NUI ausgelöst und **`success`/`fail` zurückgebend** — nutzbar für Fahrzeug-Lockpick,
> Türen/ATM-Hacks, Reparaturen u. a. quer durch die anderen Systeme.
### 📱 Handy (`resources/[aether]/aether-phone/`) ✅ teilweise migriert
Öffnen mit **`F1`** — setzt das **Handy-Item** voraus. Ohne SIM-Karte gibt es kein Netz
(keine Anrufe, keine Nachrichten), bei leerem Akku geht es gar nicht erst an.
**Server-gestützt (echt):**
- **Telefonnummer** je Charakter (`555-XXXX`, automatisch vergeben und eindeutig)
- **Kontakte** (anlegen, bearbeiten, löschen)
- **Nachrichten** zwischen Spielern — werden zugestellt, gespeichert und auch bei
geschlossenem Handy als Hinweis gemeldet
- **Anrufe** zwischen Spielern mit vollem Ablauf: klingeln, annehmen, auflegen, besetzt,
nicht erreichbar; verpasste Anrufe landen im Verlauf. Notrufe (110/112) lösen ein Event
für die spätere Leitstelle aus
- **Bank**-Kachel zeigt echten Kontostand und IBAN
- **Sicherheit:** PIN und Face-ID liegen in der Datenbank, die **PIN verlässt den Server nie**
- **Akku** läuft langsam leer (1 % alle 3 Minuten) und lässt sich mit einem **Akku-Item** tauschen
- Einstellungen (Theme, Wallpaper, Dock) werden gespeichert
> **Noch lokal (bewusst):** Wetter, Rechner, Uhr/Wecker, Notizen, Musik, Kamera/Galerie, Birdy,
> InstaPic, Staat, Dispatch, Gelbe Seiten und Darkchat laufen weiterhin ohne Server. Jede
> dieser Apps wäre ein eigenes Feature — sie funktionieren, halten ihre Daten aber nur
> innerhalb einer Sitzung.
**Export für andere Module:**
```lua
exports['aether-phone']:HoleNummer(source)
exports['aether-phone']:SendeNachricht('555-0182', 'EMS', 'Deine Rechnung: 1.500 €')
```
**Enthaltene Apps & Funktionen:**
- Telefon (Wähler, Verlauf, Kontakte, animierter Anruf)
- Nachrichten (Chats, Senden)
- Bank (Kontostand, Überweisen, Transaktionen)
- Staat (Staatskasse mit Graph, Einnahmen/Ausgaben, Projekt-Abstimmungen)
- Dispatch (Notfall an die Leitstelle melden, vordefinierte Gründe)
- Birdy (Social Media), InstaPic/Galerie, Kamera
- Uhr (Live, Wecker stellen/löschen), Notizen (bearbeiten/löschen)
- Wetter, Rechner, Garage, Gelbe Seiten, Musik, Darkchat (freischaltbar)
- Einstellungen (Theme, Wallpaper, anpassbares Dock, Sicherheit)
**RP-Mechaniken (als Prototyp angelegt):**
- **Ersteinrichtung** beim Erststart: Code festlegen + Face-ID einrichten
- **Entsperren** per Face-ID (Apple-artige Scan-Animation) oder Code
- **Hardware als Items**: Handy, SIM-Karte und Akku (leer werdend) — später ingame kombinierbar
- **Push-Benachrichtigungen** (Banner + Sperrbildschirm, wegwischbar)
- **Gesperrte Apps** per Gamemechanik freischaltbar (z. B. Darkchat)
> Alle "Server-Daten" (Kontakte, Konten, Chats, Hardware-Zustand …) sind bewusst
> vom UI getrennt im `spielerZustand`/Datenlisten gehalten, um später an
> NUI-Callbacks und die Datenbank angebunden zu werden.
### 🏧 Bankautomat (`resources/[aether]/aether-bank/`) ✅ migriert
Öffnet sich an **echten Geldautomaten** in der Welt (`prop_atm_01/02/03`, `prop_fleeca_atm`) —
in die Nähe gehen und **`E`** drücken. Schließen mit `Esc`.
**Sicherheit:**
- Die **PIN verlässt den Server nie.** Sie wird ausschließlich serverseitig gegen
`aether_characters.bank_pin` geprüft; die Oberfläche kennt sie nicht.
- Jede Sitzung beginnt mit der PIN-Eingabe; Buchungen sind erst nach erfolgreicher
Anmeldung möglich (der Server merkt sich das je Spieler).
- Beträge werden auf positive Ganzzahlen und ein Maximum geprüft, Deckung prüft der Core.
**Funktionen:** Auszahlen (Konto → Bargeld), Einzahlen (Bargeld → Konto), Überweisen per **IBAN**
(funktioniert auch an **Offline-Spieler** — dann direkt in der Datenbank), PIN ändern, Kontoauszug
und Statistik.
> **Echte Daten statt erfundener Kurve:** Der Kontostand-Verlauf wird aus den tatsächlichen
> Buchungen abgeleitet (jede Buchung speichert den Stand danach). Bei zu wenig Historie bleibt
> die Linie flach — es wird nichts dazuerfunden.
> **Browser-Fallback:** Ohne FiveM zeigt die Seite Beispieldaten mit Test-PIN `1234` —
> `resources/[aether]/aether-bank/html/index.html` bleibt eigenständig ansehbar.
**Funktionen:**
- **PIN-Eingabe** (Login) und **PIN-Änderung** (aktuelle → neue → bestätigen)
- **Auszahlen** (Schnellbeträge + eigener Betrag, „Geld entnehmen"-Animation)
- **Einzahlen** und **Überweisen** (mit Bestätigung)
- **Kontoauszug** (laufender Saldo, Filter Eingang/Ausgang)
- **Statistiken**: Aktien-artiges Verlaufsdiagramm (glatte Linie + Flächenverlauf,
Hover-Fadenkreuz, Zeitraum 7T/30T/12M), Einnahmen/Ausgaben, Sparquote
Besonderheit: Das Display ist standardmäßig durchscheinend und wird erst bei
Maus-Hover voll sichtbar (verlässt die Maus das Display, sinkt die Opazität).
> Kontodaten (Saldo, IBAN, PIN, Transaktionen) liegen getrennt im `konto`-Objekt,
> bereit für die Anbindung an DB/Server.
### 🎒 Inventar (`resources/[aether]/aether-inventory/`) ✅ migriert
**Vollständig server-geprüft.** Die Oberfläche entscheidet nichts mehr selbst — sie schickt nur
Wünsche („verschiebe Slot 3 auf Slot 7"), der Server prüft und antwortet mit dem neuen Zustand.
Öffnen im Spiel mit **Taste `I`**, schließen mit `Esc`.
**Slot-Aufteilung** (alles in einer Tabelle, die Nummer bestimmt den Bereich):
Tasche `0–24` · Hotbar `100–104` · Ausrüstung `200–204`
**Serverseitige Prüfungen:**
- Gültigkeit jeder Slotnummer, Passform der Ausrüstungsplätze, Tauschbarkeit
- **Traglast** (30 kg) bei Aufheben, Geben und Hinzufügen
- **Entfernung** beim Aufheben (3 m) und Geben (3 m) — kein Zugriff quer über die Karte
- Beim Geben wird **zuerst** geprüft, ob der Empfänger tragen kann; schlägt die Übergabe fehl,
geht das Item an den Absender zurück (nichts verschwindet)
**Item-Registry** (`shared/items.lua`) wird von Client *und* Server geladen, damit beide
garantiert dieselben Werte verwenden. Benutzen wertet der Server aus (Essen/Trinken über
`AendereZustand` im Core, Heilung über ein Client-Event).
**Exports für andere Module** (Shop, Jobs, Dokumente …):
```lua
exports['aether-inventory']:GebeItem(source, 'wasser', 2)
exports['aether-inventory']:ZaehleItem(source, 'dietrich')
exports['aether-inventory']:EntferneItem(source, 'bargeld', 500)
```
**Fallengelassene Items** liegen als sichtbare **Kartons** in der Welt und sind **dauerhaft**
gespeichert (Tabelle `aether_drops`) — sie überleben Serverneustarts:
- Beim Fallenlassen wird zufällig einer von drei Kartons gewählt
(`prop_cardbordbox_03a/04a/05a`), damit alle Drops einheitlich aussehen
- Props werden **nur lokal** je Client erzeugt und ab 30 m Entfernung wieder entfernt
- Aufheben per **`E`** am Karton (mit Hinweis über dem Objekt) oder per Drag & Drop im Inventar
- Drops älter als 48 h werden beim Serverstart aufgeräumt (`DROP_MAX_STUNDEN`)
> **Browser-Fallback:** Ohne FiveM zeigt die Seite Beispieldaten und rechnet das Gewicht selbst —
> `resources/[aether]/aether-inventory/html/index.html` bleibt eigenständig ansehbar.
**Funktionen:**
- **Drag & Drop** zwischen Tasche, Ausrüstung, Hotbar, Boden und Spielern
- **Gewichtssystem** (getragene kg / Limit), Einzelgewicht je Item
- **Hover-Details** (Name nach Seltenheit gefärbt, Kategorie, Beschreibung, Gewicht)
- **3D-artiger Avatar** mit Ausrüstungs-Slots (Helm, Brust, Hose, Schuhe, Schmuck) + Hotbar 1–5
- **Fallenlassen** (auf Boden ziehen), **Geben** (auf Spieler ziehen)
- **Splitten** per Rechtsklick → Slider; Rechtsklick-Menü (Benutzen, Ausrüsten, Geben, Fallenlassen)
- **Doppelklick** = Benutzen / Ausrüsten
- **Assets & Waffen**: Handy zeigt verbaute Komponenten (SIM, Akku), Waffen zeigen
Seriennummer + Aufsätze (Basis für späteren Waffenschein)
- **Anonyme Spieler**: Namen erscheinen erst, wenn die Person bekannt ist
(im Spiel via Ausweis/Visitenkarte) — sonst „Unbekannt · ID #xxxx"
> Item-Registry (`itemDefs`) und Orte (Tasche, Ausrüstung, Hotbar, Boden) sind
> getrennt gehalten, bereit für die Anbindung an das Server-Inventar.
### 👛 Börse & Dokumente (`resources/[aether]/aether-documents/`) ✅ migriert
Öffnen mit **`F2`** — setzt voraus, dass du mindestens eine **Börse** (Item aus dem 24/7)
dabei hast. Die Kartendesigns des Prototyps sind unverändert übernommen.
**Datenmodell:** Tabelle `aether_documents`. Name und Geburtsdatum kommen **live aus dem
Charakter**, nur die dokumentspezifischen Felder (Nummern, Fahrklassen, registrierte Waffen)
liegen im Dokument — so muss nichts doppelt gepflegt werden.
**Automatisch** beim ersten Laden: Personalausweis, Gesundheitskarte, Visitenkarte.
**Behördlich** (nur über Exports ausstellbar): Führerschein, Waffenschein.
**Anzahl Börsen = Anzahl `boerse`-Items im Inventar** — kaufst du eine zweite Börse im 24/7,
erscheint sie als weiterer Reiter (je max. 10 Dokumente).
**Vorzeigen** an Personen in 4 m Reichweite; der Empfänger sieht die Karte als Vollbild.
Dabei werden die Daten des *Zeigenden* gerendert, nicht die eigenen.
**Exports:**
```lua
-- Wird vom Shop (Ammu-Nation) abgefragt:
exports['aether-documents']:HatWaffenschein(source)
exports['aether-documents']:HatDokument(source, 'fs')
-- Für ein Polizei-Modul (stellt aus / entzieht):
exports['aether-documents']:StelleAus(charakterId, 'ws', { waffen = {...} }, 'LSPD')
exports['aether-documents']:Entziehe(charakterId, 'ws')
```
> **Damit greift die Waffenschein-Prüfung im Shop.** Ammu-Nation gibt lizenzpflichtige Waren
> jetzt nur noch an Spieler mit gültigem, nicht entzogenem Waffenschein heraus.
**Dokumente (jeweils eigenes Design):**
- **Personalausweis** (Guilloché, Wappen, MRZ-Zeile)
- **Führerschein** (EU-Stil, Sternenkreis, Fahrklassen)
- **Waffenschein** (Behörden-Look, Stempel, Tabelle mehrerer registrierter Waffen mit Seriennummer)
- **Gesundheitskarte** (eGK mit Chip)
- **Visitenkarte** (nur Name + Telefonnummer, für Handykontakt)
**Funktionen:**
- **Börse = ein Item**, das alle Karten enthält
- **Multi-Börse**: mehrere Börsen (im Shop kaufbar), je **max. 10 Slots**, Wechsel per Tabs
- **Verschieben** von Dokumenten zwischen Börsen
- **Vorzeigen** (präsentieren, optional gezielt an eine — anonymisierte — Person)
- **Verlieren** (Dokument aus der Börse entfernen)
> Stammdaten liegen zentral im `person`-Objekt, Karten-Designs pro Typ in
> `kartenRenderer`, Börsen in `boersen[]` (mit `MAX_SLOTS`). Die Waffen-Seriennummern
> passen zu den Items im Inventar — Basis für spätere Waffenschein-Prüfungen.
### 🛒 Läden (`resources/[aether]/aether-shop/`) ✅ migriert
Öffnet sich an echten Filialen in der Welt — **10 24/7-Läden** und **9 Ammu-Nations** mit
Karten-Markierungen. In die Nähe gehen und **`E`** drücken, schließen mit `Esc`.
**Der Server rechnet den Warenkorb komplett neu durch:**
- **Preise kommen immer vom Server** — was der Client schickt, sind nur Produkt-IDs und Mengen
- Führt der Laden das Produkt überhaupt? Ist der **Bestand** da? Ist die **Menge** plausibel?
- **Waffenschein** bei lizenzpflichtigen Waren, **Deckung** über den Core, **Traglast** über das Inventar
- Steht die Entfernung zur Filiale? (kein Einkaufen aus der Ferne)
- Passt etwas nicht ins Inventar, wird der Anteil **automatisch erstattet**
**Bestand & Nachschub:** Jede Filiale hat eigene Bestände im Speicher, die alle 15 Minuten um
10 % aufgefüllt werden.
**Gekaufte Waren landen im Inventar** — dafür wurde die Item-Registry um alle fehlenden Waren
erweitert (Getränke, Snacks, Elektronik, Zubehör, Waffen, Munition, Aufsätze). Munition wird
paketweise verkauft (z. B. „9mm ×30" liefert 30 Stück).
> **Browser-Fallback:** Ohne FiveM rechnet die Seite lokal mit Beispieldaten und zeigt beide
> Läden zum Umschalten — `resources/[aether]/aether-shop/html/index.html`.
**Enthaltene Läden (oben umschaltbar, Akzentfarbe passt sich an):**
- **LS 24/7** — Getränke, Snacks, Gesundheit, Werkzeug, Elektronik (Handy, SIM, Akku), Zubehör (Börse, Rucksack)
- **Ammu-Nation** — Waffen, Munition, Aufsätze, Schutz (mit „Waffenschein nötig"-Badge)
**Funktionen:**
- Kategorien-Sidebar (mit Anzahl) + Live-Suche
- Produktkarten mit Bestand, Angeboten (Rabatt), Menge-im-Korb
- Warenkorb mit Mengen-Steppern, Zwischensummen, Gesamtpreis
- Zahlung per Bargeld oder Karte (Guthaben-Anzeige + Deckungsprüfung)
- Kassenbeleg nach dem Kauf; Bestand/Geld werden aktualisiert
> Zentrale Produkt-Registry (`produkte`) + `shops[]`, die nur Produkt-IDs referenzieren —
> beliebige weitere Läden mit wenigen Zeilen anlegbar. Geld liegt in `spieler`
> (später an Bank/Item-System koppeln).
### 🚓 Polizei & Rettungsdienst — *neu zu bauen*
Das gemeinsame Fraktions-CAD wurde entfernt. Polizei und Rettungsdienst sollen als
**zwei getrennte Module** entstehen (`aether-police`, `aether-ems`).
Die Datenbanktabellen aus dem CAD bleiben bestehen und sind weiterverwendbar:
`aether_records` (Personenakten), `aether_wanted` (Fahndungen), `aether_jail` (Haft),
`aether_treasury` (Staatskasse).
Offene Anschlusspunkte, die auf ein solches Modul warten:
- **Notruf-Events** `aether:phone:notruf` (110/112 aus dem Handy) und `aether:death:notruf`
(Verletzt-Screen) werden ausgelöst, aber derzeit von niemandem verarbeitet
- **Waffenschein**: `exports['aether-documents']:StelleAus(charakterId, 'ws', …)` — solange
niemand ausstellt, bleiben Waffen bei Ammu-Nation gesperrt
- **Kennzeichenabfrage**: `exports['aether-garage']:HoleHalter(kennzeichen)`
- **Wiederbelebung**: `exports['aether-death']:Wiederbeleben(quelle, helferQuelle)`
### 🧑 Charakterauswahl (`resources/[aether]/aether-character/`) ✅ migriert
Vollständig an den Server angebunden: Die Liste kommt aus der Datenbank, Erstellen und Löschen
laufen über geprüfte NUI-Callbacks, und die Auswahl lässt den Core den Charakter spawnen.
Im Browser weiterhin ansehbar (zeigt dann Beispieldaten):
`resources/[aether]/aether-character/html/index.html`.
**Serverseitige Prüfungen:** Namen (nur Buchstaben, 2–32 Zeichen), Geburtsdatum (TT.MM.JJJJ,
Jahr 1900–2010), Slotgrenze aus `Config.MaxCharaktere` und Eigentumsprüfung bei Spielen/Löschen.
**3D-Vorschau:** `client/vorschau.lua` spawnt einen **lokalen Ped** als lebende Vorschau und
richtet eine Kamera darauf; die NUI liegt mit einem **transparenten Bereich** darüber. Jede
Änderung an Slidern oder Paletten wird sofort auf den Ped übertragen (gebündelt, damit Slider
die Verbindung nicht fluten). Enthalten:
- Ansichten **Gesicht / Körper** (Kamerafahrt statt SVG-Wechsel)
- **Drehen** des Peds per ◀ ▶ unter der Vorschau
- **Geschlechtswechsel** erzeugt den Ped mit dem passenden Modell neu (Drehung/Ansicht bleiben)
- Auf der Auswahlseite zeigt der Ped den gerade **markierten Charakter**
**Aussehen:** `client/aussehen.lua` überträgt die Werte des Erstellers auf den GTA-Ped
(Kopfform, Hautton, Frisur, Haar-/Augenfarbe, Bart, Augenbrauen, Gesichts-Slider,
Kleidungsfarben). Die Zuordnungstabellen sind bewusst als **Annäherung** angelegt und leicht
nachjustierbar.
> **Browser-Fallback:** Ohne FiveM (Datei direkt öffnen) fehlt der 3D-Ped. Die Seite erkennt das
> und schaltet auf das frühere Kasten-Layout mit der stilisierten **SVG-Vorschau** zurück — das
> Modul bleibt also weiter eigenständig ansehbar.
**Auswahl:**
- Bis zu 5 Charakter-Slots mit Portrait-Vorschau, Name, Job, Spielzeit
- Aktionen: Spielen, Löschen (kein Bearbeiten — Änderungen am Charakter erfolgen ingame)
- „+ Neuen Charakter erstellen"
**Ersteller (live aktualisierte Vektor-Vorschau, Gesicht-/Körper-Ansicht):**
- Identität (Vor-/Nachname, Geschlecht, Geburtsdatum, Herkunft)
- Gesicht (Hautton, Augenfarbe)
- Merkmale (Slider: Gesichtsbreite, Kiefer, Nase, Lippen, Körperbau)
- Haare & Bart (Frisuren, Haarfarben, Augenbrauen, Bartstile)
- Kleidung (Oberteil/Hose/Schuhe-Farben)
> Das Aussehen liegt als kompaktes `aussehen`-Objekt je Charakter (Slider 0–100),
> später auf FiveM-Ped-Komponenten (Heritage/Features/Components) mappbar. Die Vorschau
> ist eine stilisierte SVG-Darstellung, kein 3D-Ped.
### 🚗 Garage (`resources/[aether]/aether-garage/`) ✅ migriert
Vier öffentliche Garagen (Legion Square, Sandy Shores, Del Perro, Paleto) mit
Karten-Markierungen — hingehen und **`E`** drücken. Nutzt die Tabelle `aether_vehicles`.
**Regeln, die der Server durchsetzt:**
- **Standort-Regel:** Ausparken nur an der Garage, wo das Fahrzeug wirklich steht — sonst
nennt die Meldung den tatsächlichen Standort
- **Zugangs-Regel:** Es werden nur Garagen angezeigt, zu denen Zugang besteht. Haus-Garagen
fragen bei `aether-immobilien` an (noch nicht migriert → bleiben verschlossen)
- **Besitz** bei jeder Aktion, **Entfernung** beim Öffnen und Einparken
- Beschlagnahmte Fahrzeuge lassen sich nur gegen **Gebühr** auslösen
**Fahrzeuge werden serverseitig erzeugt** und überleben dadurch Serverneustarts:
- Die Position ausgeparkter Fahrzeuge wird **alle 30 Sekunden** sowie beim Stoppen der
Ressource gesichert (Spalten `pos_x/pos_y/pos_z/heading`)
- Beim Serverstart stehen sie wieder **exakt dort, wo sie zuletzt waren**
- Lässt sich ein Fahrzeug nicht setzen (z. B. Modell entfernt), wandert es zurück in seine
Garage statt verloren zu gehen
- Eigenschaften, die nur clientseitig gesetzt werden können (Kennzeichen, Farbe, Zustand),
reicht der Server über einen **State Bag** weiter; der Client wendet sie an, sobald das
Fahrzeug bei ihm auftaucht
**Zustand wird echt gespeichert:** Beim Einparken liest der Client Tank, Motor- und
Karosserieschaden vom Fahrzeug; der Server begrenzt die Werte und schreibt sie zurück.
Während der Fahrt wird der Zustand zusätzlich alle 30 Sekunden gemeldet, damit er auch bei
einem unerwarteten Serverstopp nicht verloren geht.
**Kilometerstand:** GTA führt keinen Tacho — der Client zählt die gefahrene Strecke selbst
mit (Sprünge durch Teleport/Nachladen werden ignoriert), der Server addiert sie beim
Einparken auf und lässt den Stand nie sinken.
**Neue Charaktere** bekommen ein Startfahrzeug (Blista in Legion Square, abschaltbar).
**Exports:**
```lua
exports['aether-garage']:GebeFahrzeug(charakterId, 'sultan', 'legion', { name = 'Sultan' })
exports['aether-garage']:Beschlagnahmen(kennzeichen) -- fürs Polizei-CAD
exports['aether-garage']:HoleHalter(kennzeichen) -- Kennzeichenabfrage
```
**Funktionen:**
- **Auto-Vorschau** je Fahrzeugtyp (Sport/Limousine/SUV/Pickup/Kleinwagen/Muscle/Motorrad),
parametrisches SVG in Fahrzeugfarbe
- **San-Andreas-Kennzeichen** (Stile SA/Gelb/Schwarz) — Farbe **fix**, wird nur beim Kauf festgelegt
- **Zustand** (Tank/Motor/Karosserie), Kilometerstand, Klasse
- **Standort-Regel**: Ausparken nur an der Garage, wo das Fahrzeug steht; Ansehen aller
zugänglichen Garagen erlaubt („Alle"-Übersicht), Einparken lagert ins aktuelle Standort-Garage
- **Zugangs-Regel**: sichtbar sind nur **öffentliche** Garagen und **Haus-Garagen mit Zugang**
(Besitz/berechtigt); Garagen ohne Zugang erscheinen nicht
> `garagen` (mit `typ`/`zugang`), `standort` (physischer Standort), `zugaenglich()`.
> Später `standort` an die Spielerposition und `zugang` an Haus-/Schlüsselbesitz koppeln.
> Kennzeichen passen konzeptionell zur Kennzeichenabfrage im CAD.
### 🏡 AetherImmos — Immobilien (`immobilien/`)
Web-Prototyp des **Immobilien-/Wohnungs-Systems** — reines HTML/CSS/JS.
Zum Ansehen `immobilien/index.html` im Browser öffnen.
**Bereiche:**
- **Markt (AetherImmos)** — Angebote mit stilisiertem Objekt-„Foto" je Typ (Wohnung/Haus/Villa/
Gewerbe), Filter + Suche, Detailansicht mit Ausstattung
- **Kaufmenü** (separat) — Kaufpreis + Notar-/Bearbeitungsgebühr, Zahlung per Konto/Bargeld;
beim Kauf gibt es **5 Hausschlüssel (Items)**
- **Meine Immobilien** — Betreten, **Schlüssel-Verwaltung** (Anzahl gehaltener Schlüssel,
**Nachmachen** beim Schlüsseldienst; Weitergabe erfolgt übers Inventar, da Schlüssel = Item),
**Verkauf mit anteiliger Rückzahlung** (60 % des Kaufpreises)
> `marktplatz` (Angebote), `meine` (Besitz mit `schluessel`-Anzahl + `kaufpreis`),
> `RUECKKAUF=0.6`, `START_SCHLUESSEL=5`. Schlüssel koppeln ans Inventar-System; die Zugangslogik
> passt zur Haus-Garagen-Zugangsregel in `garage/`.
### 👕 Aether Threads — Kleidungsladen (`clothing/`)
Web-Prototyp des **Bekleidungsladens** mit Live-Vorschau — reines HTML/CSS/JS.
Zum Ansehen `clothing/index.html` im Browser öffnen.
**Funktionen:**
- **Live-Charaktervorschau** (SVG-Figur), Zoom **Ganzkörper / Kopf**
- Kategorien: Kopfbedeckung (Cap/Beanie/Hut/Helm), Brille, Maske (Halbmaske/Sturmhaube),
Oberteil (T-Shirt/Hemd/Hoodie/Jacke/Anzug), Hose (Jeans/Cargo/Shorts/Anzughose),
Schuhe (Sneaker/Stiefel/Sandalen), Kette (Silber/Gold)
- **Farbwahl** je Teil; bereits getragene Teile als „im Besitz" markiert (kostenlos)
- **Warenkorb** der geänderten Teile, **Zahlung** Bargeld/Karte (Deckungsprüfung),
„Kaufen & anziehen" / „Zurücksetzen"
> `kategorien` (Stile + Preise), `farben`, `getragen` (Besitz) vs. `outfit` (Anprobe).
> Der Avatar koppelt konzeptionell an dieselben Komponenten wie der Charakter-Ersteller (`character/`).
### 🛡️ Admin-Dashboard (`admin/`)
Web-Prototyp des **zentralen Server-Admin-Dashboards** — reines HTML/CSS/JS.
Zum Ansehen `admin/index.html` im Browser öffnen.
**Bereiche:**
- **Dashboard** (Live-KPIs, 24h-Chart, Schnellaktionen, Ressourcen-Status, Admin-Log)
- **Weltkarte** mit Live-Standorten + **Quick-Menü** je Spieler (Verwalten/Kamera/TP/Freeze/Kick)
- **Spieler**: Tabelle + gruppiertes Aktions-Panel (Teleport, Zustand, Geben, Moderation:
Heal/Revive/Freeze/God/Mute, Geld, Item, Fahrzeug, Job, Warn/Kick/Ban)
- **Fahrzeuge**: Bild-Spawner (Autos/Bikes/Helis/Boote/Flugzeuge) + **Tuning** (Motor/Getriebe/
Bremsen/Panzerung/Turbo/Lack), Reparieren/Herholen/Löschen
- **Live-Kameras** (WebRTC-Spectate, Einzel- & Multi-Cam-Views), **Kill-/Deathcams**
(manuell speicherbar, sonst Auto-Löschung nach 24 h)
- **Staatsprojekte** (aktivierbar nach positiver Abstimmung aus der Handy-Staat-App)
- **Immobilien**, **Fraktionen** (Gehalt/h, erstellen/löschen), **Wirtschaft**
- **Weltsteuerung** (Zeit/Wetter/Blackout/Cleanup), **Ankündigungen**
- **Bans & Warns**, **Reports/Support**, **Ressourcen**, **Audit-Log**, **Admin-Team**, **Einstellungen**
> Die „Kamera-Feeds" sind stilisierte Simulationen (in FiveM WebRTC-Stream). Datenmodelle
> (`players`, `weltFahrzeuge`, `staatsprojekte`, `killcams`, `fraktionen` …) sind vom UI getrennt.
### 🎖️ Fraktions-/Gang-Verwaltung (`factions/`)
Web-Prototyp der **Fraktions-/Gang-Verwaltung** aus Führungssicht — reines HTML/CSS/JS.
Zum Ansehen `factions/index.html` im Browser öffnen. Oben Fraktion + „Als Rang ansehen" wählen.
**Funktionen:**
- **Mehrere Fraktionen** (Gangs & legaler Betrieb), Akzentfarbe passt sich an
- **Mitglieder**: Roster, Befördern/Degradieren/Kicken (rang-gated), Einladen
- **Ränge & Rechte**: Gehalt je Rang + Rechte-Matrix (Einladen/Kicken/Befördern/Kasse/Ränge/
Territorien/Fahrzeuge/Einstellungen), Ränge anlegen/löschen; Leitung hat alle Rechte
- **Kasse**: Einzahlen/Auszahlen, **Payday** (zieht alle Gehälter), Transaktionsliste
- **Territorien** (nur Gangs): Karte mit Kontroll-% (kontrolliert/umkämpft/feindlich),
Angreifen/Verstärken/Ausbauen (Ausbau kostet Kasse, erhöht Einnahmen/h)
- **Fraktionsfahrzeuge** (gemeinsame Garage, Freigabe ab Rang), **Logbuch**, **Einstellungen**
> Rechtesystem greift überall über `darf(recht)` (abhängig vom gewählten Rang). Datenmodell
> `fraktionen[]` (Ränge/Mitglieder/Kasse/Territorien/Fahrzeuge/Logs). Deckt die im Admin-Panel
> referenzierten Fraktionen ab.
### 💼 Aether Jobs (`resources/[aether]/aether-jobs/`) ✅ migriert
Am **Jobcenter** (Karten-Markierung) mit **`E`** öffnen; wer im Dienst ist, erreicht die
Arbeitsansicht jederzeit mit **`J`**. Acht Jobs mit Level und XP, gespeichert in `aether_jobs`.
**Gearbeitet wird in der Welt, nicht im Menü.** Jeder Arbeitsschritt hat einen echten Ort:
- Nach dem Antreten schließt sich das Menü und eine **Route auf der Karte** führt zum Arbeitsort
- Dort steht ein **Bodenmarker**; in Reichweite erscheint `[E] Paket laden`
- Die Handlung läuft mit **Animation und Fortschrittsbalken** ab (Angeln 12 s, Baum fällen 10 s,
Erz abbauen 12 s …), erst danach meldet der Client sie
- Eine **Aufgabenanzeige** am Bildschirmrand zeigt durchgehend Aufgabe, Ziel und Entfernung
- Jobs mit Fahrzeug (Lieferdienst, Müllabfuhr, Taxi, Trucker) bekommen beim Antreten ein
**Dienstfahrzeug** gestellt, das bei Feierabend wieder verschwindet
**Der Server prüft alles Wesentliche:**
- **Ortsprüfung:** Der Spieler muss tatsächlich am Arbeitsort stehen, sonst wird abgelehnt
- **Zeitprüfung:** Die Handlung muss ihre vorgesehene Dauer gebraucht haben
- **Aufträge, Orte und Löhne entstehen ausschließlich serverseitig** — der Client meldet nur
„Schritt erledigt" und kann weder Ziel noch Bezahlung beeinflussen
- Nur **ein Job gleichzeitig**; Level/XP und Verdienst werden pro Job dauerhaft gespeichert
- **Levelbonus** von 5 % je Level fließt in den Lohn ein, Höchstlevel 20
**Exports:**
```lua
exports['aether-jobs']:HoleAktivenJob(source) -- z. B. für Job-Fahrzeuge
exports['aether-jobs']:HoleLevel(source, 'trucker')
```
**Funktionen:**
- **Jobcenter** mit 8 Jobs (Lieferdienst, Müllabfuhr, Taxi, Trucker, Tankwart, Angeln,
Holzfäller, Bergbau) inkl. Level/XP je Job
- **Dienst an/aus** (nur ein Job gleichzeitig), Akzentfarbe passt sich dem Job an
- **Arbeits-Loop**: mehrschrittige Aufträge mit Fortschrittsanzeige, Lohn-Vorschau,
Fang/Ausbeute-Flavor; bei Abschluss Geld + XP, ggf. Level-Up (erhöht den Lohn)
- **Schicht-Statistik** (Verdient, Aufträge, Dienstzeit-Timer), **Feierabend**
- **Statistik** über alle Jobs (Level/XP)
> `jobs[]` (mit `schritte` + `auftrag(level)`), `fortschritt` (Level/XP je Job), `spieler`
> (Bargeld/Konto). Aktionen später an echte Ingame-Zonen/Fahrten koppelbar.
### 🎰 Aether Casino (`casino/`)
Web-Prototyp des **Casino-UIs** mit fünf spielbaren Glücksspielen — reines HTML/CSS/JS.
Zum Ansehen `casino/index.html` im Browser öffnen.
**Guthaben & Session:**
- **Guthaben** (Casino-Chips) getrennt vom **Bargeld**; **Aufladen/Auszahlen** zwischen beiden
- **Session-Bilanz** (Netto-Gewinn/-Verlust der aktuellen Sitzung, grün/rot)
- Wiederverwendbare **Einsatz-Steuerung** (Schnell-Chips 50/100/500/1000 + „Max")
**Spiele (mit bewusst kalkuliertem Hausvorteil):**
- **Spielautomat** — 3 gewichtete Walzen, Auszahlungstabelle, 7️⃣7️⃣7️⃣-Jackpot ×180 (RTP ~90 %)
- **Blackjack** — gegen den Dealer (Ziehen/Stehen/Verdoppeln), echter Blackjack ×2, Dealer zieht bis 17
- **Roulette** — einfache Chancen (×2), Dutzende (×3), Einzelzahl (×36), mehrere Einsätze gleichzeitig
- **Glücksrad** — 12 Felder, Multiplikator ×0 bis ×5 (Hausvorteil ~21 %)
- **Münzwurf** — Kopf oder Zahl, ×2 bei richtiger Wahl
> Zustand liegt getrennt: `spieler` (Bargeld), `guthaben` (Chips), `session` (Ein/Aus). Jedes Spiel
> hält sein eigenes Datenmodell (`slotReel`/`slotPay`, `bj`, `rlt.bets`, `wSegs`) — Gewichtungen/
> Multiplikatoren zentral definiert und leicht anpassbar. Der Spielwechsel erstattet offene Einsätze.
## Konventionen
- Jedes System ist eine eigenständige `index.html` (self-contained, ohne externe Abhängigkeiten).
- Daten/Zustand sind bewusst vom UI getrennt gehalten — vorbereitet für die spätere
Anbindung an FiveM (NUI-Callbacks) und Datenbank.