aether-framework/resources/[aether]/aether-bank/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

181 lines
5.9 KiB
Lua

-- =====================================================================
-- Aether Bank — Clientlogik
-- Findet Geldautomaten in der Welt, oeffnet die Oberflaeche und reicht
-- alle Wuensche an den Server weiter. Entschieden wird dort.
-- =====================================================================
-- Ist der Automat gerade offen?
local istOffen = false
-- Ist der Spieler im Spiel?
local istGeladen = false
-- Taste E zum Benutzen
local TASTE_BENUTZEN = 38
-- Modelle, die als Geldautomat gelten
local AUTOMATEN = {
'prop_atm_01',
'prop_atm_02',
'prop_atm_03',
'prop_fleeca_atm',
}
-- Vorberechnete Hashes der Automaten-Modelle
local automatenHashes = {}
for _, name in ipairs(AUTOMATEN) do
automatenHashes[#automatenHashes + 1] = GetHashKey(name)
end
--- Schickt eine Nachricht an die Oberflaeche
local function SendeAnNui(nachricht)
SendNuiMessage(json.encode(nachricht))
end
--- Zeigt eine Meldung oben links im Spiel
local function ZeigeSpielmeldung(text)
if not text or text == '' then return end
BeginTextCommandThefeedPost('STRING')
AddTextComponentSubstringPlayerName(text)
EndTextCommandThefeedPostTicker(false, true)
end
--- Schliesst den Automaten
local function Schliessen()
if not istOffen then return end
istOffen = false
SetNuiFocus(false, false)
SendeAnNui({ aktion = 'schliessen' })
TriggerServerEvent('aether:bank:schliessen')
pcall(function() exports['aether-hud']:SetzeSichtbar(true) end)
end
-- ---------------------------------------------------------------------
-- Ereignisse
-- ---------------------------------------------------------------------
AddEventHandler('aether:client:bereit', function()
istGeladen = true
end)
--- Server erlaubt das Oeffnen: Oberflaeche zeigen (PIN-Eingabe folgt)
RegisterNetEvent('aether:bank:zeige', function()
istOffen = true
SetNuiFocus(true, true)
pcall(function() exports['aether-hud']:SetzeSichtbar(false) end)
SendeAnNui({ aktion = 'oeffnen' })
end)
--- Ergebnis der PIN-Pruefung
RegisterNetEvent('aether:bank:pinErgebnis', function(erfolg, konto)
SendeAnNui({ aktion = 'pinErgebnis', erfolg = erfolg, konto = konto })
end)
--- Aktualisierter Kontostand nach einer Buchung
RegisterNetEvent('aether:bank:konto', function(konto)
konto.aktion = 'konto'
SendeAnNui(konto)
end)
--- Erfolgsmeldung (wird als Abschlussbildschirm angezeigt)
RegisterNetEvent('aether:bank:erfolg', function(titel, text)
SendeAnNui({ aktion = 'erfolg', titel = titel, text = text })
end)
--- Ablehnung einer Aktion
RegisterNetEvent('aether:bank:fehler', function(text)
if istOffen then
SendeAnNui({ aktion = 'fehler', text = text })
else
ZeigeSpielmeldung(text)
end
end)
--- Benachrichtigung ausserhalb des Automaten (z. B. Geld erhalten)
RegisterNetEvent('aether:bank:benachrichtigung', function(text)
ZeigeSpielmeldung(text)
end)
-- ---------------------------------------------------------------------
-- Automaten in der Naehe finden und benutzen
-- ---------------------------------------------------------------------
CreateThread(function()
while true do
local pause = 700
if istGeladen and not istOffen then
local position = GetEntityCoords(PlayerPedId())
-- Naechstgelegenen Automaten suchen
local automat = nil
for _, hash in ipairs(automatenHashes) do
local objekt = GetClosestObjectOfType(position.x, position.y, position.z,
1.6, hash, false, false, false)
if objekt ~= 0 then automat = objekt break end
end
if automat then
pause = 0 -- fuer die Textanzeige jeden Frame laufen
local automatPos = GetEntityCoords(automat)
SetTextFont(4)
SetTextScale(0.32, 0.32)
SetTextColour(255, 255, 255, 215)
SetTextCentre(true)
SetTextOutline()
SetTextEntry('STRING')
AddTextComponentString('[E] Geldautomat benutzen')
SetDrawOrigin(automatPos.x, automatPos.y, automatPos.z + 0.8, 0)
DrawText(0.0, 0.0)
ClearDrawOrigin()
if IsControlJustReleased(0, TASTE_BENUTZEN) then
TriggerServerEvent('aether:bank:oeffnen')
end
end
end
Wait(pause)
end
end)
-- ---------------------------------------------------------------------
-- NUI-Callbacks
-- ---------------------------------------------------------------------
RegisterNUICallback('schliessen', function(_, rueckgabe)
Schliessen()
rueckgabe({ ok = true })
end)
RegisterNUICallback('pinPruefen', function(daten, rueckgabe)
TriggerServerEvent('aether:bank:pinPruefen', tostring(daten.pin or ''))
rueckgabe({ ok = true })
end)
RegisterNUICallback('pinAendern', function(daten, rueckgabe)
TriggerServerEvent('aether:bank:pinAendern', tostring(daten.alt or ''), tostring(daten.neu or ''))
rueckgabe({ ok = true })
end)
RegisterNUICallback('auszahlen', function(daten, rueckgabe)
TriggerServerEvent('aether:bank:auszahlen', tonumber(daten.betrag) or 0)
rueckgabe({ ok = true })
end)
RegisterNUICallback('einzahlen', function(daten, rueckgabe)
TriggerServerEvent('aether:bank:einzahlen', tonumber(daten.betrag) or 0)
rueckgabe({ ok = true })
end)
RegisterNUICallback('ueberweisen', function(daten, rueckgabe)
TriggerServerEvent('aether:bank:ueberweisen',
tostring(daten.ziel or ''), tonumber(daten.betrag) or 0, tostring(daten.zweck or ''))
rueckgabe({ ok = true })
end)
-- ---------------------------------------------------------------------
-- Aufraeumen
-- ---------------------------------------------------------------------
AddEventHandler('onResourceStop', function(ressource)
if ressource ~= GetCurrentResourceName() then return end
SetNuiFocus(false, false)
end)