- 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>
132 lines
5.2 KiB
Lua
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
|