357 lines
11 KiB
Lua
357 lines
11 KiB
Lua
local QBCore = exports['qb-core']:GetCoreObject()
|
|
local isMenuOpen = false
|
|
local currentLicenseData = nil
|
|
|
|
-- Debug-Funktion
|
|
local function debugPrint(message)
|
|
if Config.Debug then
|
|
print("^2[License-System Client] " .. message .. "^7")
|
|
end
|
|
end
|
|
|
|
-- Hilfsfunktionen
|
|
local function getClosestPlayer()
|
|
local players = GetActivePlayers()
|
|
local closestDistance = -1
|
|
local closestPlayer = -1
|
|
local ped = PlayerPedId()
|
|
local coords = GetEntityCoords(ped)
|
|
|
|
for i = 1, #players do
|
|
local target = GetPlayerPed(players[i])
|
|
if target ~= ped then
|
|
local targetCoords = GetEntityCoords(target)
|
|
local distance = #(coords - targetCoords)
|
|
if closestDistance == -1 or closestDistance > distance then
|
|
closestPlayer = GetPlayerServerId(players[i])
|
|
closestDistance = distance
|
|
end
|
|
end
|
|
end
|
|
|
|
return closestPlayer, closestDistance
|
|
end
|
|
|
|
-- URL-Validierung
|
|
local function isValidUrl(url)
|
|
if not url or url == "" then return true end -- Optional
|
|
return string.match(url, Config.Validation.url_pattern) ~= nil
|
|
end
|
|
|
|
-- Datum-Validierung
|
|
local function isValidDate(date)
|
|
if not date or date == "" then return false end
|
|
if not string.match(date, Config.Validation.date_pattern) then return false end
|
|
|
|
local day, month, year = date:match("(%d+)%.(%d+)%.(%d+)")
|
|
day, month, year = tonumber(day), tonumber(month), tonumber(year)
|
|
|
|
if not day or not month or not year then return false end
|
|
if day < 1 or day > 31 then return false end
|
|
if month < 1 or month > 12 then return false end
|
|
if year < 1900 or year > 2100 then return false end
|
|
|
|
return true
|
|
end
|
|
|
|
-- Bild-URL validieren
|
|
local function validateImageUrl(url, callback)
|
|
if not url or url == "" then
|
|
callback(true, Config.UI.default_avatar)
|
|
return
|
|
end
|
|
|
|
if not isValidUrl(url) then
|
|
callback(false, "Ungültige URL")
|
|
return
|
|
end
|
|
|
|
-- Dateiformat prüfen
|
|
local extension = string.lower(url:match("%.([^%.]+)$") or "")
|
|
local isValidFormat = false
|
|
|
|
for _, format in ipairs(Config.UI.allowed_image_formats) do
|
|
if extension == format then
|
|
isValidFormat = true
|
|
break
|
|
end
|
|
end
|
|
|
|
if not isValidFormat then
|
|
callback(false, "Ungültiges Bildformat. Erlaubt: " .. table.concat(Config.UI.allowed_image_formats, ", "))
|
|
return
|
|
end
|
|
|
|
callback(true, url)
|
|
end
|
|
|
|
-- Erweiterte Lizenz-Erstellung mit benutzerdefinierten Feldern
|
|
local function openCustomLicenseCreation(targetId, licenseType)
|
|
debugPrint("Öffne erweiterte Lizenz-Erstellung für: " .. licenseType)
|
|
|
|
local config = Config.LicenseTypes[licenseType]
|
|
if not config then
|
|
QBCore.Functions.Notify("Unbekannter Lizenztyp!", "error")
|
|
return
|
|
end
|
|
|
|
-- NUI-Daten vorbereiten
|
|
local formData = {
|
|
licenseType = licenseType,
|
|
config = config,
|
|
targetId = targetId,
|
|
validation = Config.Validation,
|
|
ui = Config.UI
|
|
}
|
|
|
|
debugPrint("Sende Daten an NUI: " .. json.encode(formData))
|
|
|
|
-- NUI öffnen
|
|
SetNuiFocus(true, true)
|
|
SendNUIMessage({
|
|
action = "openCustomLicenseForm",
|
|
data = formData
|
|
})
|
|
|
|
isMenuOpen = true
|
|
end
|
|
|
|
-- Standard-Lizenz-Erstellung (ohne benutzerdefinierte Felder)
|
|
local function openStandardLicenseCreation(targetId, licenseType)
|
|
debugPrint("Öffne Standard-Lizenz-Erstellung für: " .. licenseType)
|
|
|
|
local config = Config.LicenseTypes[licenseType]
|
|
if not config then
|
|
QBCore.Functions.Notify("Unbekannter Lizenztyp!", "error")
|
|
return
|
|
end
|
|
|
|
local classes = {}
|
|
if config.classes then
|
|
for classKey, classLabel in pairs(config.classes) do
|
|
table.insert(classes, {key = classKey, label = classLabel})
|
|
end
|
|
end
|
|
|
|
-- Standard-Erstellung (für Lizenzen ohne custom_fields)
|
|
TriggerServerEvent('license-system:server:issueLicense', targetId, licenseType, classes)
|
|
end
|
|
|
|
-- Hauptmenü öffnen
|
|
local function openMainMenu()
|
|
debugPrint("Öffne Hauptmenü")
|
|
|
|
local targetId, distance = getClosestPlayer()
|
|
|
|
local menuData = {
|
|
licenseTypes = Config.LicenseTypes,
|
|
targetId = targetId,
|
|
targetDistance = distance,
|
|
hasTarget = targetId ~= -1 and distance <= 3.0
|
|
}
|
|
|
|
SetNuiFocus(true, true)
|
|
SendNUIMessage({
|
|
action = "openMainMenu",
|
|
data = menuData
|
|
})
|
|
|
|
isMenuOpen = true
|
|
end
|
|
|
|
-- NUI-Callbacks
|
|
RegisterNUICallback('closeMenu', function(data, cb)
|
|
debugPrint("Schließe Menü")
|
|
SetNuiFocus(false, false)
|
|
isMenuOpen = false
|
|
cb('ok')
|
|
end)
|
|
|
|
RegisterNUICallback('requestLicense', function(data, cb)
|
|
debugPrint("Lizenz angefordert für Spieler: " .. data.targetId)
|
|
TriggerServerEvent('license-system:server:requestLicense', data.targetId)
|
|
cb('ok')
|
|
end)
|
|
|
|
RegisterNUICallback('requestMyLicense', function(data, cb)
|
|
debugPrint("Eigene Lizenz angefordert: " .. (data.licenseType or "alle"))
|
|
TriggerServerEvent('license-system:server:requestMyLicense', data.licenseType)
|
|
cb('ok')
|
|
end)
|
|
|
|
RegisterNUICallback('requestPlayerLicenses', function(data, cb)
|
|
debugPrint("Alle Lizenzen angefordert für Spieler: " .. data.targetId)
|
|
TriggerServerEvent('license-system:server:requestPlayerLicenses', data.targetId)
|
|
cb('ok')
|
|
end)
|
|
|
|
RegisterNUICallback('openLicenseCreation', function(data, cb)
|
|
debugPrint("Lizenz-Erstellung angefordert: " .. data.licenseType)
|
|
|
|
local config = Config.LicenseTypes[data.licenseType]
|
|
if config and config.custom_fields and #config.custom_fields > 0 then
|
|
openCustomLicenseCreation(data.targetId, data.licenseType)
|
|
else
|
|
openStandardLicenseCreation(data.targetId, data.licenseType)
|
|
end
|
|
|
|
cb('ok')
|
|
end)
|
|
|
|
RegisterNUICallback('validateImageUrl', function(data, cb)
|
|
debugPrint("Validiere Bild-URL: " .. (data.url or "leer"))
|
|
|
|
validateImageUrl(data.url, function(isValid, result)
|
|
cb({
|
|
valid = isValid,
|
|
url = isValid and result or Config.UI.default_avatar,
|
|
error = not isValid and result or nil
|
|
})
|
|
end)
|
|
end)
|
|
|
|
RegisterNUICallback('submitCustomLicense', function(data, cb)
|
|
debugPrint("Benutzerdefinierte Lizenz eingereicht")
|
|
debugPrint("Daten: " .. json.encode(data))
|
|
|
|
local licenseType = data.licenseType
|
|
local targetId = data.targetId
|
|
local customData = data.customData
|
|
local classes = data.classes or {}
|
|
|
|
-- Validierung
|
|
local config = Config.LicenseTypes[licenseType]
|
|
if not config then
|
|
cb({success = false, error = "Unbekannter Lizenztyp"})
|
|
return
|
|
end
|
|
|
|
-- Pflichtfelder prüfen
|
|
for _, field in ipairs(config.custom_fields or {}) do
|
|
if field.required then
|
|
local value = customData[field.name]
|
|
if not value or value == "" then
|
|
cb({success = false, error = "Feld '" .. field.label .. "' ist erforderlich"})
|
|
return
|
|
end
|
|
|
|
-- Spezielle Validierung
|
|
if field.type == "date" and not isValidDate(value) then
|
|
cb({success = false, error = "Ungültiges Datum in Feld '" .. field.label .. "'"})
|
|
return
|
|
end
|
|
|
|
if field.type == "url" and not isValidUrl(value) then
|
|
cb({success = false, error = "Ungültige URL in Feld '" .. field.label .. "'"})
|
|
return
|
|
end
|
|
end
|
|
end
|
|
|
|
-- An Server senden
|
|
TriggerServerEvent('license-system:server:issueCustomLicense', targetId, licenseType, customData, classes)
|
|
|
|
cb({success = true})
|
|
end)
|
|
|
|
RegisterNUICallback('revokeLicense', function(data, cb)
|
|
debugPrint("Lizenz-Entzug angefordert: " .. data.licenseType .. " für Spieler: " .. data.targetId)
|
|
TriggerServerEvent('license-system:server:revokeLicense', data.targetId, data.licenseType)
|
|
cb('ok')
|
|
end)
|
|
|
|
-- Server-Events
|
|
RegisterNetEvent('license-system:client:receiveLicense', function(licenseData)
|
|
debugPrint("Lizenz erhalten")
|
|
|
|
if licenseData then
|
|
debugPrint("Zeige Lizenz: " .. licenseData.license.license_type)
|
|
|
|
SetNuiFocus(true, true)
|
|
SendNUIMessage({
|
|
action = "showLicense",
|
|
data = licenseData
|
|
})
|
|
else
|
|
debugPrint("Keine Lizenz gefunden")
|
|
QBCore.Functions.Notify("Keine Lizenz gefunden!", "error")
|
|
end
|
|
end)
|
|
|
|
RegisterNetEvent('license-system:client:receiveMyLicense', function(licenseData, licenseType)
|
|
debugPrint("Eigene Lizenz erhalten: " .. (licenseType or "unbekannt"))
|
|
|
|
if licenseData then
|
|
debugPrint("Zeige eigene Lizenz: " .. licenseData.license.license_type)
|
|
|
|
SetNuiFocus(true, true)
|
|
SendNUIMessage({
|
|
action = "showMyLicense",
|
|
data = licenseData
|
|
})
|
|
else
|
|
debugPrint("Keine eigene Lizenz gefunden")
|
|
QBCore.Functions.Notify("Du hast keine " .. (Config.LicenseTypes[licenseType] and Config.LicenseTypes[licenseType].label or "Lizenz") .. "!", "error")
|
|
end
|
|
end)
|
|
|
|
RegisterNetEvent('license-system:client:receivePlayerLicenses', function(licenses, targetId, targetName)
|
|
debugPrint("Spieler-Lizenzen erhalten: " .. #licenses .. " für " .. targetName)
|
|
|
|
SetNuiFocus(true, true)
|
|
SendNUIMessage({
|
|
action = "showPlayerLicenses",
|
|
data = {
|
|
licenses = licenses,
|
|
targetId = targetId,
|
|
targetName = targetName,
|
|
licenseTypes = Config.LicenseTypes
|
|
}
|
|
})
|
|
end)
|
|
|
|
RegisterNetEvent('license-system:client:licenseIssued', function(targetId, licenseType)
|
|
debugPrint("Lizenz ausgestellt: " .. licenseType)
|
|
QBCore.Functions.Notify("Lizenz erfolgreich ausgestellt!", "success")
|
|
end)
|
|
|
|
RegisterNetEvent('license-system:client:licenseRevoked', function(targetId, licenseType)
|
|
debugPrint("Lizenz entzogen: " .. licenseType)
|
|
QBCore.Functions.Notify("Lizenz erfolgreich entzogen!", "success")
|
|
end)
|
|
|
|
RegisterNetEvent('license-system:client:refreshMenu', function()
|
|
debugPrint("Menü-Refresh angefordert")
|
|
if isMenuOpen then
|
|
-- Menü neu laden falls geöffnet
|
|
Wait(500)
|
|
openMainMenu()
|
|
end
|
|
end)
|
|
|
|
-- Commands
|
|
RegisterCommand('lizenz', function()
|
|
if not isMenuOpen then
|
|
openMainMenu()
|
|
end
|
|
end, false)
|
|
|
|
RegisterCommand('ausweis', function()
|
|
TriggerServerEvent('license-system:server:requestMyLicense', 'id_card')
|
|
end, false)
|
|
|
|
-- Keybinds
|
|
RegisterKeyMapping('lizenz', 'Lizenz-System öffnen', 'keyboard', 'F6')
|
|
RegisterKeyMapping('ausweis', 'Eigenen Ausweis zeigen', 'keyboard', 'F7')
|
|
|
|
-- Cleanup
|
|
AddEventHandler('onResourceStop', function(resourceName)
|
|
if GetCurrentResourceName() == resourceName then
|
|
if isMenuOpen then
|
|
SetNuiFocus(false, false)
|
|
isMenuOpen = false
|
|
end
|
|
end
|
|
end)
|
|
|
|
debugPrint("License-System Client geladen (Erweiterte Erstellung)")
|