Main/resources/[tools]/nordi_license/client/main.lua
2025-08-04 09:24:53 +02:00

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)")