aether-framework/resources/[aether]/aether-core/client/main.lua
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

166 lines
6.1 KiB
Lua

-- =====================================================================
-- Aether Core — Clientlogik
-- Meldet sich beim Server an, spawnt den Charakter und haelt die Daten aktuell.
-- =====================================================================
Aether = Aether or {}
-- Daten des eigenen Charakters (vom Server befuellt)
Aether.SpielerDaten = nil
-- Ist der Spieler fertig geladen und im Spiel?
Aether.IstGeladen = false
-- ---------------------------------------------------------------------
-- Startvorgang
-- ---------------------------------------------------------------------
CreateThread(function()
-- Warten, bis die Spielwelt bereit ist
while not NetworkIsSessionStarted() do
Wait(100)
end
-- Standard-Spawnverhalten von FiveM unterbinden.
-- Abgesichert, falls spawnmanager nicht laeuft (dann uebernimmt der Core allein).
local erfolg = pcall(function()
exports.spawnmanager:setAutoSpawn(false)
end)
if not erfolg then
Aether.Debug('spawnmanager nicht verfuegbar — Core spawnt eigenstaendig.')
end
-- Bildschirm schwarz halten, bis der Charakter geladen ist
DoScreenFadeOut(0)
SetEntityVisible(PlayerPedId(), false, false)
Aether.Debug('Client bereit — fordere Spielerdaten an.')
TriggerServerEvent('aether:server:spielerBereit')
end)
-- ---------------------------------------------------------------------
-- Spieler wurde geladen: Ped setzen und spawnen
-- ---------------------------------------------------------------------
RegisterNetEvent('aether:client:spielerGeladen', function(daten)
Aether.SpielerDaten = daten
-- Passendes Standardmodell laden (bis der Charakter-Ersteller migriert ist)
local modellName = Config.StandardPed[daten.geschlecht] or Config.StandardPed.m
local modell = GetHashKey(modellName)
RequestModel(modell)
local versuche = 0
while not HasModelLoaded(modell) and versuche < 100 do
Wait(50)
versuche = versuche + 1
end
if HasModelLoaded(modell) then
SetPlayerModel(PlayerId(), modell)
SetModelAsNoLongerNeeded(modell)
else
Aether.Fehler('Ped-Modell konnte nicht geladen werden: ' .. modellName)
end
-- Spieler an die gespeicherte Position setzen
local ped = PlayerPedId()
local pos = daten.position or Config.SpawnPunkt
SetEntityCoordsNoOffset(ped, pos.x + 0.0, pos.y + 0.0, pos.z + 0.0, false, false, false)
SetEntityHeading(ped, pos.heading or 0.0)
-- Zustand wiederherstellen
SetEntityHealth(ped, daten.leben or 200)
FreezeEntityPosition(ped, false)
SetEntityVisible(ped, true, false)
-- Warten, bis die Umgebung geladen ist, dann Bild freigeben
local wartezeit = 0
while not HasCollisionLoadedAroundEntity(ped) and wartezeit < 100 do
Wait(50)
wartezeit = wartezeit + 1
end
ShutdownLoadingScreen()
ShutdownLoadingScreenNui()
DoScreenFadeIn(1000)
Aether.IstGeladen = true
Aether.Info(('Willkommen, %s %s!'):format(daten.vorname, daten.nachname))
-- Andere Ressourcen (HUD, Handy, Inventar) informieren.
-- WICHTIG: anderer Name als das Netz-Event, sonst ruft sich dieser
-- Handler endlos selbst auf.
TriggerEvent('aether:client:bereit', daten)
end)
-- ---------------------------------------------------------------------
-- Aktualisierungen vom Server
-- ---------------------------------------------------------------------
RegisterNetEvent('aether:client:geldAktualisiert', function(geld)
if not Aether.SpielerDaten then return end
Aether.SpielerDaten.bargeld = geld.bargeld
Aether.SpielerDaten.konto = geld.konto
Aether.SpielerDaten.schwarzgeld = geld.schwarzgeld
-- Weiterreichen ans HUD
TriggerEvent('aether:client:geldGeaendert', geld)
end)
RegisterNetEvent('aether:client:zustandAktualisiert', function(zustand)
if not Aether.SpielerDaten then return end
Aether.SpielerDaten.hunger = zustand.hunger
Aether.SpielerDaten.durst = zustand.durst
Aether.SpielerDaten.ausdauer = zustand.ausdauer
-- Weiterreichen ans HUD
TriggerEvent('aether:client:zustandGeaendert', zustand)
end)
--- Schaden durch Hunger/Durst zufuegen
RegisterNetEvent('aether:client:erleideSchaden', function(menge)
local ped = PlayerPedId()
local leben = GetEntityHealth(ped)
SetEntityHealth(ped, math.max(0, leben - (menge or 5)))
end)
-- ---------------------------------------------------------------------
-- Position regelmaessig an den Server melden (fuer das Speichern)
-- ---------------------------------------------------------------------
CreateThread(function()
while true do
Wait(10000) -- alle 10 Sekunden
if Aether.IstGeladen then
local ped = PlayerPedId()
local koordinaten = GetEntityCoords(ped)
TriggerServerEvent('aether:server:aktualisierePosition', {
x = Aether.Runde(koordinaten.x, 2),
y = Aether.Runde(koordinaten.y, 2),
z = Aether.Runde(koordinaten.z, 2),
heading = Aether.Runde(GetEntityHeading(ped), 2),
})
-- Lebenswert mitschicken, damit er beim Speichern stimmt
TriggerServerEvent('aether:server:aktualisiereZustand', {
leben = GetEntityHealth(ped),
})
end
end
end)
-- ---------------------------------------------------------------------
-- Kein Charakter vorhanden (spaeter uebernimmt das aether-character)
-- ---------------------------------------------------------------------
RegisterNetEvent('aether:client:keinCharakter', function()
Aether.Fehler('Kein Charakter vorhanden — Charaktererstellung ist noch nicht migriert.')
end)
-- =====================================================================
-- EXPORTS fuer andere Module
-- Beispiel: local daten = exports['aether-core']:HoleSpielerDaten()
-- =====================================================================
--- Liefert die Daten des eigenen Charakters
exports('HoleSpielerDaten', function()
return Aether.SpielerDaten
end)
--- Ist der Spieler fertig geladen?
exports('IstGeladen', function()
return Aether.IstGeladen
end)