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

196 lines
7.2 KiB
Lua

-- =====================================================================
-- aether-police — Server-Schnittstelle
--
-- Ein einziges Netz-Event bedient alle Module. Jede Anfrage durchläuft
-- Dienstprüfung und Rechteprüfung, bevor sie ein Modul erreicht.
-- =====================================================================
local Core = exports['aether-core']
-- ---------------------------------------------------------------------
-- Tablet öffnen
-- ---------------------------------------------------------------------
RegisterNetEvent('aether:police:oeffnen', function()
local quelle = source
local beamter = Dienst.Hole(quelle)
if not beamter then
-- Noch nicht im Dienst: Personalakte prüfen und Anmeldung anbieten
local charakterId = Core:HoleCharakterId(quelle)
if not charakterId then return end
local geprueft, fehler = Dienst.LadeBeamten(quelle, charakterId)
if not geprueft then
TriggerClientEvent('aether:police:fehler', quelle, fehler)
return
end
TriggerClientEvent('aether:police:anmeldung', quelle, {
name = geprueft.name,
dienstnummer = geprueft.dienstnummer,
rolleName = geprueft.rolleName,
abteilung = geprueft.abteilung,
behoerde = Polizei.Config.Behoerde,
})
return
end
TriggerClientEvent('aether:police:zeige', quelle, {
behoerde = Polizei.Config.Behoerde,
kuerzel = Polizei.Config.Kuerzel,
module = Kern.SichtbareModule(beamter),
beamter = {
name = beamter.name, dienstnummer = beamter.dienstnummer,
rolle = beamter.rolle, rolleName = beamter.rolleName,
abteilung = beamter.abteilung, status = beamter.status,
leitstelle = Dienst.Leitstelle() == quelle,
},
status = Polizei.Config.Dienststatus,
abteilungen = Polizei.Config.Abteilungen,
})
end)
-- ---------------------------------------------------------------------
-- Dienst
-- ---------------------------------------------------------------------
RegisterNetEvent('aether:police:dienstAntreten', function()
local quelle = source
local beamter, fehler = Dienst.Antreten(quelle)
if not beamter then
TriggerClientEvent('aether:police:fehler', quelle, fehler)
return
end
TriggerClientEvent('aether:police:zeige', quelle, {
behoerde = Polizei.Config.Behoerde,
kuerzel = Polizei.Config.Kuerzel,
module = Kern.SichtbareModule(beamter),
beamter = {
name = beamter.name, dienstnummer = beamter.dienstnummer,
rolle = beamter.rolle, rolleName = beamter.rolleName,
abteilung = beamter.abteilung, status = beamter.status,
leitstelle = Dienst.Leitstelle() == quelle,
},
status = Polizei.Config.Dienststatus,
abteilungen = Polizei.Config.Abteilungen,
})
end)
RegisterNetEvent('aether:police:dienstBeenden', function()
local quelle = source
Dienst.Beenden(quelle)
TriggerClientEvent('aether:police:schliessen', quelle)
end)
RegisterNetEvent('aether:police:status', function(status)
local quelle = source
if type(status) ~= 'string' then return end
Dienst.SetzeStatus(quelle, status)
end)
RegisterNetEvent('aether:police:leitstelle', function(zielQuelle)
local quelle = source
local erfolg, fehler = Dienst.SetzeLeitstelle(quelle,
type(zielQuelle) == 'number' and zielQuelle or nil)
if not erfolg and fehler then
TriggerClientEvent('aether:police:fehler', quelle, fehler)
end
end)
-- ---------------------------------------------------------------------
-- Zentraler Modul-Aufruf
--
-- Die Oberfläche schickt { modul, aktion, daten, ruf }. Der `ruf` ist
-- eine laufende Nummer, damit die Antwort zugeordnet werden kann.
-- ---------------------------------------------------------------------
RegisterNetEvent('aether:police:aufruf', function(modulId, aktion, daten, ruf)
local quelle = source
if type(modulId) ~= 'string' or type(aktion) ~= 'string' then return end
local beamter = Dienst.Hole(quelle)
if not beamter then
TriggerClientEvent('aether:police:antwort', quelle, ruf, nil,
'Du bist nicht im Dienst.')
return
end
local ergebnis, fehler = Kern.FuehreAus(quelle, beamter, modulId, aktion, daten)
TriggerClientEvent('aether:police:antwort', quelle, ruf, ergebnis, fehler)
end)
-- ---------------------------------------------------------------------
-- Eingehende Notrufe aus anderen Modulen
--
-- Sie erzeugen einen Einsatz mit Status „offen". Zugewiesen wird
-- ausschliesslich von der Leitstelle — nie automatisch.
-- ---------------------------------------------------------------------
--- Notruf aus dem Handy (110)
AddEventHandler('aether:phone:notruf', function(quelle, fraktionId, nummer)
if fraktionId ~= 'lspd' and fraktionId ~= 'polizei' then return end
local position = GetEntityCoords(GetPlayerPed(quelle))
EinsatzEingang({
titel = 'Notruf über Telefon',
kategorie = 'notruf',
prioritaet = 2,
ort = 'Position des Anrufers',
beschreibung = ('Eingehender Anruf von %s.'):format(nummer or 'unbekannt'),
position = { x = position.x, y = position.y, z = position.z },
quelle = 'notruf',
})
end)
-- =====================================================================
-- EXPORTS — Schnittstelle für externe Systeme
-- Damit lassen sich Notrufe und Hinweise von aussen einspeisen, ohne
-- dass am Kern etwas geändert werden muss.
-- =====================================================================
--- Meldet einen Notruf an die Polizei.
--- Er erscheint als offener Einsatz — zugewiesen wird er nie automatisch.
exports('MeldeNotruf', function(daten)
if type(daten) ~= 'table' or not daten.titel then return nil end
return EinsatzEingang(daten)
end)
--- Erstellt einen Hinweis für alle Beamten im Dienst
exports('MeldeHinweis', function(daten)
if type(daten) ~= 'table' or not daten.titel then return false end
Hinweise.Erstelle(nil, daten)
return true
end)
--- Ist ein Spieler als Polizeibeamter im Dienst?
exports('IstImDienst', function(quelle)
return Dienst.Hole(quelle) ~= nil
end)
--- Liefert die Dienstdaten eines Beamten (ohne Rechtetabelle)
exports('HoleBeamten', function(quelle)
local beamter = Dienst.Hole(quelle)
if not beamter then return nil end
return {
charakterId = beamter.charakterId,
name = beamter.name,
dienstnummer = beamter.dienstnummer,
rolle = beamter.rolle,
rolleName = beamter.rolleName,
abteilung = beamter.abteilung,
status = beamter.status,
}
end)
--- Erlaubt fremden Ressourcen, ein eigenes Modul zu registrieren
exports('RegistriereModul', function(beschreibung)
return Kern.RegistriereModul(beschreibung)
end)
--- Erlaubt fremden Ressourcen, eine Aktion beizusteuern
exports('RegistriereAktion', function(modulId, aktion, recht, funktion)
Kern.RegistriereAktion(modulId, aktion, recht, funktion)
return true
end)