aether-framework/resources/[aether]/aether-core/server/database.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

132 lines
5.2 KiB
Lua

-- =====================================================================
-- Aether Core — Datenbankzugriff (oxmysql)
-- Kapselt alle SQL-Abfragen, damit der Rest des Codes kein SQL enthaelt.
-- =====================================================================
Aether = Aether or {}
Aether.DB = {}
-- ---------------------------------------------------------------------
-- Benutzer
-- ---------------------------------------------------------------------
--- Legt einen Benutzer an, falls er noch nicht existiert, und gibt ihn zurueck
--- @param lizenz string Rockstar-Lizenz des Spielers
--- @param name string Aktueller Spielername
--- @return table Benutzerdatensatz
function Aether.DB.HoleOderErstelleBenutzer(lizenz, name)
local vorhandene = MySQL.query.await(
'SELECT * FROM aether_users WHERE license = ?', { lizenz })
if vorhandene and vorhandene[1] then
-- Namen und Zeitstempel aktualisieren
MySQL.update.await(
'UPDATE aether_users SET name = ?, last_seen = NOW() WHERE license = ?',
{ name, lizenz })
return vorhandene[1]
end
-- Neuen Benutzer anlegen
MySQL.insert.await(
'INSERT INTO aether_users (license, name) VALUES (?, ?)', { lizenz, name })
Aether.Info(('Neuer Benutzer angelegt: %s (%s)'):format(name, lizenz))
local neue = MySQL.query.await(
'SELECT * FROM aether_users WHERE license = ?', { lizenz })
return neue[1]
end
-- ---------------------------------------------------------------------
-- Charaktere
-- ---------------------------------------------------------------------
--- Laedt alle nicht geloeschten Charaktere eines Benutzers
--- @param lizenz string Rockstar-Lizenz
--- @return table Liste der Charaktere
function Aether.DB.HoleCharaktere(lizenz)
return MySQL.query.await(
'SELECT * FROM aether_characters WHERE license = ? AND deleted = 0 ORDER BY last_played DESC',
{ lizenz }) or {}
end
--- Laedt einen einzelnen Charakter anhand seiner ID
--- @param charakterId number Charakter-ID
--- @return table|nil
function Aether.DB.HoleCharakter(charakterId)
local ergebnis = MySQL.query.await(
'SELECT * FROM aether_characters WHERE id = ? AND deleted = 0', { charakterId })
return ergebnis and ergebnis[1] or nil
end
--- Legt einen neuen Charakter an und gibt dessen ID zurueck
--- @param lizenz string Rockstar-Lizenz
--- @param daten table Felder: firstname, lastname, dob, gender, nationality, appearance
--- @return number Neue Charakter-ID
function Aether.DB.ErstelleCharakter(lizenz, daten)
return MySQL.insert.await([[
INSERT INTO aether_characters
(license, firstname, lastname, dob, gender, nationality, appearance,
cash, bank, iban, job, job_grade)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
]], {
lizenz,
daten.firstname or 'Max',
daten.lastname or 'Mustermann',
daten.dob or '1995-01-01',
daten.gender or 'm',
daten.nationality or 'Los Santos',
daten.appearance and json.encode(daten.appearance) or nil,
Config.StartWerte.bargeld,
Config.StartWerte.konto,
Aether.ErzeugeIban(),
Config.StartWerte.job,
Config.StartWerte.jobRang,
})
end
--- Speichert den aktuellen Stand eines Charakters zurueck in die Datenbank
--- @param charakterId number Charakter-ID
--- @param daten table Zu speichernde Werte
function Aether.DB.SpeichereCharakter(charakterId, daten)
MySQL.update([[
UPDATE aether_characters SET
cash = ?, bank = ?, dirty_money = ?,
job = ?, job_grade = ?, faction = ?, faction_rank = ?,
health = ?, hunger = ?, thirst = ?, stamina = ?,
position = ?, is_dead = ?, playtime = ?, last_played = NOW()
WHERE id = ?
]], {
daten.cash, daten.bank, daten.dirty_money,
daten.job, daten.job_grade, daten.faction, daten.faction_rank,
daten.health, daten.hunger, daten.thirst, daten.stamina,
json.encode(daten.position or Config.SpawnPunkt),
daten.is_dead and 1 or 0,
daten.playtime or 0,
charakterId,
})
end
--- Markiert einen Charakter als geloescht (Slot wird wieder frei)
--- @param charakterId number Charakter-ID
--- @param lizenz string Lizenz zur Sicherheit (nur eigene Charaktere loeschbar)
function Aether.DB.LoescheCharakter(charakterId, lizenz)
MySQL.update.await(
'UPDATE aether_characters SET deleted = 1 WHERE id = ? AND license = ?',
{ charakterId, lizenz })
end
-- ---------------------------------------------------------------------
-- Transaktionen (Bank-Modul)
-- ---------------------------------------------------------------------
--- Schreibt eine Banktransaktion mit
--- @param charakterId number Charakter-ID
--- @param art string deposit/withdraw/transfer/salary/fine
--- @param betrag number Betrag (positiv = Eingang)
--- @param kontostand number Kontostand nach der Buchung
--- @param bezeichnung string Verwendungszweck
function Aether.DB.SchreibeTransaktion(charakterId, art, betrag, kontostand, bezeichnung)
MySQL.insert('INSERT INTO aether_transactions (`character`, type, amount, balance, label) VALUES (?, ?, ?, ?, ?)',
{ charakterId, art, betrag, kontostand, bezeichnung or '' })
end