forked from Simnation/Main
ed
This commit is contained in:
parent
7932af55cb
commit
91f2af8b8b
2 changed files with 402 additions and 200 deletions
|
@ -4,6 +4,7 @@ local QBCore = exports['qb-core']:GetCoreObject()
|
||||||
local isMenuOpen = false
|
local isMenuOpen = false
|
||||||
local currentTarget = nil
|
local currentTarget = nil
|
||||||
local nearbyPlayers = {}
|
local nearbyPlayers = {}
|
||||||
|
local isLicenseShowing = false
|
||||||
|
|
||||||
-- Hilfsfunktionen
|
-- Hilfsfunktionen
|
||||||
local function debugPrint(message)
|
local function debugPrint(message)
|
||||||
|
@ -15,8 +16,10 @@ end
|
||||||
local function safeCallback(cb, ...)
|
local function safeCallback(cb, ...)
|
||||||
if cb and type(cb) == "function" then
|
if cb and type(cb) == "function" then
|
||||||
cb(...)
|
cb(...)
|
||||||
|
return true
|
||||||
else
|
else
|
||||||
debugPrint("^1Callback ist keine Funktion!^7")
|
debugPrint("^1FEHLER: Callback ist keine Funktion! Typ: " .. type(cb) .. "^7")
|
||||||
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -56,6 +59,7 @@ local function getNearbyPlayers(radius)
|
||||||
return a.distance < b.distance
|
return a.distance < b.distance
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
debugPrint("Gefundene Spieler in der Nähe: " .. #players)
|
||||||
return players
|
return players
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -64,7 +68,9 @@ local function hasPermission()
|
||||||
local PlayerData = QBCore.Functions.GetPlayerData()
|
local PlayerData = QBCore.Functions.GetPlayerData()
|
||||||
if not PlayerData or not PlayerData.job then return false end
|
if not PlayerData or not PlayerData.job then return false end
|
||||||
|
|
||||||
return Config.AuthorizedJobs[PlayerData.job.name] or false
|
local hasAuth = Config.AuthorizedJobs[PlayerData.job.name] or false
|
||||||
|
debugPrint("Berechtigung für Job " .. PlayerData.job.name .. ": " .. tostring(hasAuth))
|
||||||
|
return hasAuth
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Lizenz anzeigen
|
-- Lizenz anzeigen
|
||||||
|
@ -82,7 +88,7 @@ local function showLicense(licenseData)
|
||||||
})
|
})
|
||||||
|
|
||||||
SetNuiFocus(true, true)
|
SetNuiFocus(true, true)
|
||||||
isMenuOpen = true
|
isLicenseShowing = true
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Lizenz schließen
|
-- Lizenz schließen
|
||||||
|
@ -92,34 +98,72 @@ local function closeLicense()
|
||||||
})
|
})
|
||||||
|
|
||||||
SetNuiFocus(false, false)
|
SetNuiFocus(false, false)
|
||||||
isMenuOpen = false
|
isLicenseShowing = false
|
||||||
debugPrint("Lizenz geschlossen")
|
debugPrint("Lizenz geschlossen")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Spieler-Lizenz anzeigen
|
||||||
|
local function showPlayerLicense(targetId)
|
||||||
|
debugPrint("Rufe Server-Callback auf für Spieler: " .. tostring(targetId))
|
||||||
|
|
||||||
|
QBCore.Functions.TriggerCallback('license-system:server:getLicense', function(licenseData)
|
||||||
|
debugPrint("Callback-Antwort erhalten für Spieler-Lizenz")
|
||||||
|
|
||||||
|
if licenseData then
|
||||||
|
debugPrint("Lizenz-Daten erhalten: " .. licenseData.license.license_type)
|
||||||
|
showLicense(licenseData)
|
||||||
|
else
|
||||||
|
debugPrint("Keine Lizenz-Daten erhalten")
|
||||||
|
showNotification(Config.Notifications.license_not_found.message, Config.Notifications.license_not_found.type)
|
||||||
|
end
|
||||||
|
end, targetId)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Eigene Lizenz anzeigen
|
||||||
|
local function showMyLicense(licenseType)
|
||||||
|
debugPrint("Rufe Server-Callback auf für eigene Lizenz: " .. tostring(licenseType))
|
||||||
|
|
||||||
|
QBCore.Functions.TriggerCallback('license-system:server:getMyLicense', function(licenseData)
|
||||||
|
debugPrint("Eigene Lizenz Callback-Antwort erhalten")
|
||||||
|
|
||||||
|
if licenseData then
|
||||||
|
debugPrint("Eigene Lizenz-Daten erhalten: " .. licenseData.license.license_type)
|
||||||
|
showLicense(licenseData)
|
||||||
|
else
|
||||||
|
debugPrint("Keine eigene Lizenz gefunden")
|
||||||
|
local config = Config.LicenseTypes[licenseType]
|
||||||
|
local licenseName = config and config.label or licenseType
|
||||||
|
showNotification('Du hast keine ' .. licenseName .. '!', 'error')
|
||||||
|
end
|
||||||
|
end, licenseType)
|
||||||
|
end
|
||||||
|
|
||||||
-- Spieler-Lizenz-Menü
|
-- Spieler-Lizenz-Menü
|
||||||
local function openPlayerLicenseMenu(targetId, targetName)
|
local function openPlayerLicenseMenu(targetId, targetName)
|
||||||
debugPrint("Öffne Lizenz-Menü für Spieler: " .. targetName)
|
debugPrint("Öffne Lizenz-Menü für Spieler: " .. targetName .. " (ID: " .. targetId .. ")")
|
||||||
|
|
||||||
QBCore.Functions.TriggerCallback('license-system:server:getPlayerLicenses', function(licenses)
|
QBCore.Functions.TriggerCallback('license-system:server:getPlayerLicenses', function(licenses)
|
||||||
|
debugPrint("Spieler-Lizenzen Callback-Antwort erhalten, Anzahl: " .. (licenses and #licenses or 0))
|
||||||
|
|
||||||
local menuOptions = {}
|
local menuOptions = {}
|
||||||
|
|
||||||
if licenses and #licenses > 0 then
|
if licenses and #licenses > 0 then
|
||||||
for _, license in ipairs(licenses) do
|
for _, license in ipairs(licenses) do
|
||||||
local licenseConfig = Config.LicenseTypes[license.license_type] or {
|
local licenseConfig = Config.LicenseTypes[license.license_type] or {
|
||||||
label = license.license_type,
|
label = license.license_type,
|
||||||
icon = 'fas fa-id-card'
|
icon = 'fas fa-id-card',
|
||||||
|
color = '#667eea'
|
||||||
}
|
}
|
||||||
|
|
||||||
local statusIcon = license.is_active and '✅' or '❌'
|
local statusIcon = license.is_active == 1 and '✅' or '❌'
|
||||||
local statusText = license.is_active and 'Gültig' or 'Ungültig'
|
local statusText = license.is_active == 1 and 'Gültig' or 'Ungültig'
|
||||||
local expireText = license.expire_date or 'Unbegrenzt'
|
local expireText = license.expire_date or 'Unbegrenzt'
|
||||||
|
|
||||||
table.insert(menuOptions, {
|
table.insert(menuOptions, {
|
||||||
title = licenseConfig.label,
|
title = licenseConfig.label .. ' ' .. statusIcon,
|
||||||
description = 'Status: ' .. statusText .. ' | Gültig bis: ' .. expireText,
|
description = 'Status: ' .. statusText .. ' | Gültig bis: ' .. expireText,
|
||||||
icon = licenseConfig.icon,
|
icon = licenseConfig.icon,
|
||||||
onSelect = function()
|
onSelect = function()
|
||||||
-- Lizenz anzeigen
|
|
||||||
local licenseData = {
|
local licenseData = {
|
||||||
license = license,
|
license = license,
|
||||||
config = licenseConfig
|
config = licenseConfig
|
||||||
|
@ -134,24 +178,31 @@ local function openPlayerLicenseMenu(targetId, targetName)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
else
|
||||||
-- Aktionen hinzufügen
|
|
||||||
table.insert(menuOptions, {
|
table.insert(menuOptions, {
|
||||||
title = '─────────────────',
|
title = 'Keine Lizenzen gefunden',
|
||||||
|
description = 'Dieser Spieler hat keine Lizenzen',
|
||||||
|
icon = 'fas fa-exclamation-triangle',
|
||||||
disabled = true
|
disabled = true
|
||||||
})
|
})
|
||||||
|
end
|
||||||
-- Neue Lizenz ausstellen
|
|
||||||
table.insert(menuOptions, {
|
-- Aktionen hinzufügen
|
||||||
title = 'Neue Lizenz ausstellen',
|
table.insert(menuOptions, {
|
||||||
description = 'Eine neue Lizenz für diesen Spieler ausstellen',
|
title = '─────────────────',
|
||||||
icon = 'fas fa-plus',
|
disabled = true
|
||||||
onSelect = function()
|
})
|
||||||
openIssueLicenseMenu(targetId, targetName)
|
|
||||||
end
|
table.insert(menuOptions, {
|
||||||
})
|
title = 'Neue Lizenz ausstellen',
|
||||||
|
description = 'Eine neue Lizenz für diesen Spieler ausstellen',
|
||||||
-- Lizenz entziehen
|
icon = 'fas fa-plus',
|
||||||
|
onSelect = function()
|
||||||
|
openIssueLicenseMenu(targetId, targetName)
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
if licenses and #licenses > 0 then
|
||||||
table.insert(menuOptions, {
|
table.insert(menuOptions, {
|
||||||
title = 'Lizenz entziehen',
|
title = 'Lizenz entziehen',
|
||||||
description = 'Eine bestehende Lizenz entziehen',
|
description = 'Eine bestehende Lizenz entziehen',
|
||||||
|
@ -160,26 +211,8 @@ local function openPlayerLicenseMenu(targetId, targetName)
|
||||||
openRevokeLicenseMenu(targetId, targetName, licenses)
|
openRevokeLicenseMenu(targetId, targetName, licenses)
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
|
|
||||||
else
|
|
||||||
table.insert(menuOptions, {
|
|
||||||
title = 'Keine Lizenzen gefunden',
|
|
||||||
description = 'Dieser Spieler hat keine Lizenzen',
|
|
||||||
icon = 'fas fa-exclamation-triangle',
|
|
||||||
disabled = true
|
|
||||||
})
|
|
||||||
|
|
||||||
table.insert(menuOptions, {
|
|
||||||
title = 'Neue Lizenz ausstellen',
|
|
||||||
description = 'Eine neue Lizenz für diesen Spieler ausstellen',
|
|
||||||
icon = 'fas fa-plus',
|
|
||||||
onSelect = function()
|
|
||||||
openIssueLicenseMenu(targetId, targetName)
|
|
||||||
end
|
|
||||||
})
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Zurück-Option
|
|
||||||
table.insert(menuOptions, {
|
table.insert(menuOptions, {
|
||||||
title = '← Zurück',
|
title = '← Zurück',
|
||||||
icon = 'fas fa-arrow-left',
|
icon = 'fas fa-arrow-left',
|
||||||
|
@ -201,9 +234,14 @@ end
|
||||||
|
|
||||||
-- Lizenz ausstellen Menü
|
-- Lizenz ausstellen Menü
|
||||||
local function openIssueLicenseMenu(targetId, targetName)
|
local function openIssueLicenseMenu(targetId, targetName)
|
||||||
|
debugPrint("Öffne Lizenz-Ausstellungs-Menü für: " .. targetName)
|
||||||
|
|
||||||
local menuOptions = {}
|
local menuOptions = {}
|
||||||
|
|
||||||
for licenseType, config in pairs(Config.LicenseTypes) do
|
for licenseType, config in pairs(Config.LicenseTypes) do
|
||||||
|
local priceText = config.price and (config.price .. ' $') or 'Kostenlos'
|
||||||
|
local validityText = config.validity_days and (config.validity_days .. ' Tage') or 'Unbegrenzt'
|
||||||
|
|
||||||
table.insert(menuOptions, {
|
table.insert(menuOptions, {
|
||||||
title = config.label,
|
title = config.label,
|
||||||
description = config.description or 'Keine Beschreibung verfügbar',
|
description = config.description or 'Keine Beschreibung verfügbar',
|
||||||
|
@ -216,8 +254,8 @@ local function openIssueLicenseMenu(targetId, targetName)
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
metadata = {
|
metadata = {
|
||||||
{label = 'Preis', value = config.price .. ' $'},
|
{label = 'Preis', value = priceText},
|
||||||
{label = 'Gültigkeitsdauer', value = config.validity_days and (config.validity_days .. ' Tage') or 'Unbegrenzt'}
|
{label = 'Gültigkeitsdauer', value = validityText}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
@ -247,47 +285,49 @@ local function openDriversLicenseClassMenu(targetId, targetName, licenseType)
|
||||||
local function updateMenu()
|
local function updateMenu()
|
||||||
local menuOptions = {}
|
local menuOptions = {}
|
||||||
|
|
||||||
for _, class in ipairs(config.classes) do
|
if config.classes then
|
||||||
local isSelected = false
|
for _, class in ipairs(config.classes) do
|
||||||
for _, selected in ipairs(selectedClasses) do
|
local isSelected = false
|
||||||
if selected == class then
|
for _, selected in ipairs(selectedClasses) do
|
||||||
isSelected = true
|
if selected == class then
|
||||||
break
|
isSelected = true
|
||||||
end
|
break
|
||||||
end
|
|
||||||
|
|
||||||
local classDescriptions = {
|
|
||||||
['A'] = 'Motorräder',
|
|
||||||
['A1'] = 'Leichte Motorräder (bis 125ccm)',
|
|
||||||
['A2'] = 'Mittlere Motorräder (bis 35kW)',
|
|
||||||
['B'] = 'PKW (bis 3,5t)',
|
|
||||||
['BE'] = 'PKW mit Anhänger',
|
|
||||||
['C'] = 'LKW (über 3,5t)',
|
|
||||||
['CE'] = 'LKW mit Anhänger',
|
|
||||||
['D'] = 'Bus (über 8 Personen)',
|
|
||||||
['DE'] = 'Bus mit Anhänger'
|
|
||||||
}
|
|
||||||
|
|
||||||
table.insert(menuOptions, {
|
|
||||||
title = 'Klasse ' .. class .. (isSelected and ' ✅' or ''),
|
|
||||||
description = classDescriptions[class] or 'Keine Beschreibung',
|
|
||||||
icon = isSelected and 'fas fa-check-square' or 'far fa-square',
|
|
||||||
onSelect = function()
|
|
||||||
if isSelected then
|
|
||||||
-- Klasse entfernen
|
|
||||||
for i, selected in ipairs(selectedClasses) do
|
|
||||||
if selected == class then
|
|
||||||
table.remove(selectedClasses, i)
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
-- Klasse hinzufügen
|
|
||||||
table.insert(selectedClasses, class)
|
|
||||||
end
|
end
|
||||||
updateMenu()
|
|
||||||
end
|
end
|
||||||
})
|
|
||||||
|
local classDescriptions = {
|
||||||
|
['A'] = 'Motorräder',
|
||||||
|
['A1'] = 'Leichte Motorräder (bis 125ccm)',
|
||||||
|
['A2'] = 'Mittlere Motorräder (bis 35kW)',
|
||||||
|
['B'] = 'PKW (bis 3,5t)',
|
||||||
|
['BE'] = 'PKW mit Anhänger',
|
||||||
|
['C'] = 'LKW (über 3,5t)',
|
||||||
|
['CE'] = 'LKW mit Anhänger',
|
||||||
|
['D'] = 'Bus (über 8 Personen)',
|
||||||
|
['DE'] = 'Bus mit Anhänger'
|
||||||
|
}
|
||||||
|
|
||||||
|
table.insert(menuOptions, {
|
||||||
|
title = 'Klasse ' .. class .. (isSelected and ' ✅' or ''),
|
||||||
|
description = classDescriptions[class] or 'Keine Beschreibung',
|
||||||
|
icon = isSelected and 'fas fa-check-square' or 'far fa-square',
|
||||||
|
onSelect = function()
|
||||||
|
if isSelected then
|
||||||
|
-- Klasse entfernen
|
||||||
|
for i, selected in ipairs(selectedClasses) do
|
||||||
|
if selected == class then
|
||||||
|
table.remove(selectedClasses, i)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- Klasse hinzufügen
|
||||||
|
table.insert(selectedClasses, class)
|
||||||
|
end
|
||||||
|
updateMenu()
|
||||||
|
end
|
||||||
|
})
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
table.insert(menuOptions, {
|
table.insert(menuOptions, {
|
||||||
|
@ -329,6 +369,9 @@ end
|
||||||
local function confirmIssueLicense(targetId, targetName, licenseType, classes)
|
local function confirmIssueLicense(targetId, targetName, licenseType, classes)
|
||||||
local config = Config.LicenseTypes[licenseType]
|
local config = Config.LicenseTypes[licenseType]
|
||||||
local classText = classes and table.concat(classes, ', ') or 'Keine'
|
local classText = classes and table.concat(classes, ', ') or 'Keine'
|
||||||
|
local priceText = config.price and (config.price .. ' $') or 'Kostenlos'
|
||||||
|
|
||||||
|
debugPrint("Bestätige Lizenz-Ausstellung: " .. licenseType .. " für " .. targetName)
|
||||||
|
|
||||||
lib.registerContext({
|
lib.registerContext({
|
||||||
id = 'confirm_issue_license',
|
id = 'confirm_issue_license',
|
||||||
|
@ -336,19 +379,23 @@ local function confirmIssueLicense(targetId, targetName, licenseType, classes)
|
||||||
options = {
|
options = {
|
||||||
{
|
{
|
||||||
title = 'Spieler: ' .. targetName,
|
title = 'Spieler: ' .. targetName,
|
||||||
disabled = true
|
disabled = true,
|
||||||
|
icon = 'fas fa-user'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title = 'Lizenztyp: ' .. config.label,
|
title = 'Lizenztyp: ' .. config.label,
|
||||||
disabled = true
|
disabled = true,
|
||||||
|
icon = config.icon
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title = 'Klassen: ' .. classText,
|
title = 'Klassen: ' .. classText,
|
||||||
disabled = true
|
disabled = true,
|
||||||
|
icon = 'fas fa-list'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title = 'Kosten: ' .. config.price .. ' $',
|
title = 'Kosten: ' .. priceText,
|
||||||
disabled = true
|
disabled = true,
|
||||||
|
icon = 'fas fa-dollar-sign'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title = '─────────────────',
|
title = '─────────────────',
|
||||||
|
@ -359,6 +406,7 @@ local function confirmIssueLicense(targetId, targetName, licenseType, classes)
|
||||||
description = 'Lizenz jetzt ausstellen',
|
description = 'Lizenz jetzt ausstellen',
|
||||||
icon = 'fas fa-check',
|
icon = 'fas fa-check',
|
||||||
onSelect = function()
|
onSelect = function()
|
||||||
|
debugPrint("Sende Lizenz-Ausstellung an Server...")
|
||||||
TriggerServerEvent('license-system:server:issueLicense', targetId, licenseType, classes)
|
TriggerServerEvent('license-system:server:issueLicense', targetId, licenseType, classes)
|
||||||
lib.hideContext()
|
lib.hideContext()
|
||||||
end
|
end
|
||||||
|
@ -379,10 +427,12 @@ end
|
||||||
|
|
||||||
-- Lizenz entziehen Menü
|
-- Lizenz entziehen Menü
|
||||||
local function openRevokeLicenseMenu(targetId, targetName, licenses)
|
local function openRevokeLicenseMenu(targetId, targetName, licenses)
|
||||||
|
debugPrint("Öffne Lizenz-Entziehungs-Menü für: " .. targetName)
|
||||||
|
|
||||||
local menuOptions = {}
|
local menuOptions = {}
|
||||||
|
|
||||||
for _, license in ipairs(licenses) do
|
for _, license in ipairs(licenses) do
|
||||||
if license.is_active then
|
if license.is_active == 1 then
|
||||||
local config = Config.LicenseTypes[license.license_type] or {
|
local config = Config.LicenseTypes[license.license_type] or {
|
||||||
label = license.license_type,
|
label = license.license_type,
|
||||||
icon = 'fas fa-id-card'
|
icon = 'fas fa-id-card'
|
||||||
|
@ -399,11 +449,13 @@ local function openRevokeLicenseMenu(targetId, targetName, licenses)
|
||||||
options = {
|
options = {
|
||||||
{
|
{
|
||||||
title = 'Spieler: ' .. targetName,
|
title = 'Spieler: ' .. targetName,
|
||||||
disabled = true
|
disabled = true,
|
||||||
|
icon = 'fas fa-user'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title = 'Lizenztyp: ' .. config.label,
|
title = 'Lizenztyp: ' .. config.label,
|
||||||
disabled = true
|
disabled = true,
|
||||||
|
icon = config.icon
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title = '─────────────────',
|
title = '─────────────────',
|
||||||
|
@ -414,6 +466,7 @@ local function openRevokeLicenseMenu(targetId, targetName, licenses)
|
||||||
description = 'Lizenz jetzt entziehen',
|
description = 'Lizenz jetzt entziehen',
|
||||||
icon = 'fas fa-check',
|
icon = 'fas fa-check',
|
||||||
onSelect = function()
|
onSelect = function()
|
||||||
|
debugPrint("Sende Lizenz-Entziehung an Server...")
|
||||||
TriggerServerEvent('license-system:server:revokeLicense', targetId, license.license_type)
|
TriggerServerEvent('license-system:server:revokeLicense', targetId, license.license_type)
|
||||||
lib.hideContext()
|
lib.hideContext()
|
||||||
end
|
end
|
||||||
|
@ -463,6 +516,8 @@ end
|
||||||
|
|
||||||
-- Hauptmenü für Lizenz-System
|
-- Hauptmenü für Lizenz-System
|
||||||
local function openLicenseMenu()
|
local function openLicenseMenu()
|
||||||
|
debugPrint("Öffne Hauptmenü für Lizenz-System")
|
||||||
|
|
||||||
if not hasPermission() then
|
if not hasPermission() then
|
||||||
showNotification(Config.Notifications.no_permission.message, Config.Notifications.no_permission.type)
|
showNotification(Config.Notifications.no_permission.message, Config.Notifications.no_permission.type)
|
||||||
return
|
return
|
||||||
|
@ -499,6 +554,8 @@ end
|
||||||
|
|
||||||
-- Eigene Lizenzen anzeigen
|
-- Eigene Lizenzen anzeigen
|
||||||
local function showMyLicenses()
|
local function showMyLicenses()
|
||||||
|
debugPrint("Öffne Menü für eigene Lizenzen")
|
||||||
|
|
||||||
local menuOptions = {}
|
local menuOptions = {}
|
||||||
|
|
||||||
for licenseType, config in pairs(Config.LicenseTypes) do
|
for licenseType, config in pairs(Config.LicenseTypes) do
|
||||||
|
@ -507,13 +564,7 @@ local function showMyLicenses()
|
||||||
description = 'Deine ' .. config.label .. ' anzeigen',
|
description = 'Deine ' .. config.label .. ' anzeigen',
|
||||||
icon = config.icon,
|
icon = config.icon,
|
||||||
onSelect = function()
|
onSelect = function()
|
||||||
QBCore.Functions.TriggerCallback('license-system:server:getMyLicense', function(licenseData)
|
showMyLicense(licenseType)
|
||||||
if licenseData then
|
|
||||||
showLicense(licenseData)
|
|
||||||
else
|
|
||||||
showNotification('Du hast keine ' .. config.label .. '!', 'error')
|
|
||||||
end
|
|
||||||
end, licenseType)
|
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
@ -529,47 +580,100 @@ end
|
||||||
|
|
||||||
-- Events
|
-- Events
|
||||||
RegisterNetEvent('license-system:client:showLicense', function(targetId)
|
RegisterNetEvent('license-system:client:showLicense', function(targetId)
|
||||||
QBCore.Functions.TriggerCallback('license-system:server:getLicense', function(licenseData)
|
debugPrint("Event erhalten: showLicense für ID " .. tostring(targetId))
|
||||||
showLicense(licenseData)
|
showPlayerLicense(targetId)
|
||||||
end, targetId)
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
RegisterNetEvent('license-system:client:showMyLicense', function(licenseType)
|
RegisterNetEvent('license-system:client:showMyLicense', function(licenseType)
|
||||||
QBCore.Functions.TriggerCallback('license-system:server:getMyLicense', function(licenseData)
|
debugPrint("Event erhalten: showMyLicense für Typ " .. tostring(licenseType))
|
||||||
showLicense(licenseData)
|
showMyLicense(licenseType)
|
||||||
end, licenseType)
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
RegisterNetEvent('license-system:client:openCamera', function()
|
RegisterNetEvent('license-system:client:openCamera', function()
|
||||||
|
debugPrint("Event erhalten: openCamera")
|
||||||
SendNUIMessage({
|
SendNUIMessage({
|
||||||
action = 'openCamera'
|
action = 'openCamera'
|
||||||
})
|
})
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
RegisterNetEvent('license-system:client:refreshMenu', function()
|
||||||
|
debugPrint("Event erhalten: refreshMenu")
|
||||||
|
if lib.getOpenContextMenu() then
|
||||||
|
lib.hideContext()
|
||||||
|
Wait(100)
|
||||||
|
openLicenseMenu()
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
-- NUI Callbacks
|
-- NUI Callbacks
|
||||||
RegisterNUICallback('closeLicense', function(data, cb)
|
RegisterNUICallback('closeLicense', function(data, cb)
|
||||||
|
debugPrint("NUI Callback: closeLicense")
|
||||||
closeLicense()
|
closeLicense()
|
||||||
safeCallback(cb, 'ok')
|
|
||||||
|
if cb and type(cb) == "function" then
|
||||||
|
cb('ok')
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
RegisterNUICallback('savePhoto', function(data, cb)
|
RegisterNUICallback('savePhoto', function(data, cb)
|
||||||
|
debugPrint("NUI Callback: savePhoto")
|
||||||
|
|
||||||
if data.photo and data.citizenid then
|
if data.photo and data.citizenid then
|
||||||
TriggerServerEvent('license-system:server:savePhoto', data.citizenid, data.photo)
|
TriggerServerEvent('license-system:server:savePhoto', data.citizenid, data.photo)
|
||||||
safeCallback(cb, 'ok')
|
|
||||||
|
if cb and type(cb) == "function" then
|
||||||
|
cb('ok')
|
||||||
|
end
|
||||||
else
|
else
|
||||||
safeCallback(cb, 'error')
|
debugPrint("^1Fehler: Foto-Daten unvollständig^7")
|
||||||
|
|
||||||
|
if cb and type(cb) == "function" then
|
||||||
|
cb('error')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
RegisterNUICallback('takePicture', function(data, cb)
|
||||||
|
debugPrint("NUI Callback: takePicture")
|
||||||
|
|
||||||
|
-- Hier könnte eine Kamera-Funktion implementiert werden
|
||||||
|
if cb and type(cb) == "function" then
|
||||||
|
cb('ok')
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- Commands
|
-- Commands
|
||||||
RegisterCommand(Config.Commands.license.name, function()
|
RegisterCommand(Config.Commands.license.name, function()
|
||||||
|
debugPrint("Command ausgeführt: " .. Config.Commands.license.name)
|
||||||
openLicenseMenu()
|
openLicenseMenu()
|
||||||
end, Config.Commands.license.restricted)
|
end, Config.Commands.license.restricted)
|
||||||
|
|
||||||
RegisterCommand(Config.Commands.mylicense.name, function()
|
RegisterCommand(Config.Commands.mylicense.name, function()
|
||||||
|
debugPrint("Command ausgeführt: " .. Config.Commands.mylicense.name)
|
||||||
showMyLicenses()
|
showMyLicenses()
|
||||||
end, Config.Commands.mylicense.restricted)
|
end, Config.Commands.mylicense.restricted)
|
||||||
|
|
||||||
|
-- Zusätzliche Commands für schnellen Zugriff
|
||||||
|
RegisterCommand('ausweis', function()
|
||||||
|
debugPrint("Command ausgeführt: ausweis")
|
||||||
|
showMyLicense('id_card')
|
||||||
|
end, false)
|
||||||
|
|
||||||
|
RegisterCommand('führerschein', function()
|
||||||
|
debugPrint("Command ausgeführt: führerschein")
|
||||||
|
showMyLicense('drivers_license')
|
||||||
|
end, false)
|
||||||
|
|
||||||
|
RegisterCommand('waffenschein', function()
|
||||||
|
debugPrint("Command ausgeführt: waffenschein")
|
||||||
|
showMyLicense('weapon_license')
|
||||||
|
end, false)
|
||||||
|
|
||||||
|
RegisterCommand('pass', function()
|
||||||
|
debugPrint("Command ausgeführt: pass")
|
||||||
|
showMyLicense('passport')
|
||||||
|
end, false)
|
||||||
|
|
||||||
-- Keybinds
|
-- Keybinds
|
||||||
if Config.Keybinds.open_license_menu then
|
if Config.Keybinds.open_license_menu then
|
||||||
RegisterKeyMapping(Config.Commands.license.name, Config.Keybinds.open_license_menu.description, 'keyboard', Config.Keybinds.open_license_menu.key)
|
RegisterKeyMapping(Config.Commands.license.name, Config.Keybinds.open_license_menu.description, 'keyboard', Config.Keybinds.open_license_menu.key)
|
||||||
|
@ -579,17 +683,68 @@ if Config.Keybinds.show_my_licenses then
|
||||||
RegisterKeyMapping(Config.Commands.mylicense.name, Config.Keybinds.show_my_licenses.description, 'keyboard', Config.Keybinds.show_my_licenses.key)
|
RegisterKeyMapping(Config.Commands.mylicense.name, Config.Keybinds.show_my_licenses.description, 'keyboard', Config.Keybinds.show_my_licenses.key)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Cleanup
|
-- ESC-Taste zum Schließen der Lizenz
|
||||||
|
CreateThread(function()
|
||||||
|
while true do
|
||||||
|
Wait(0)
|
||||||
|
|
||||||
|
if isLicenseShowing then
|
||||||
|
if IsControlJustPressed(0, 322) then -- ESC-Taste
|
||||||
|
closeLicense()
|
||||||
|
end
|
||||||
|
else
|
||||||
|
Wait(500)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Cleanup und Initialisierung
|
||||||
AddEventHandler('onResourceStop', function(resourceName)
|
AddEventHandler('onResourceStop', function(resourceName)
|
||||||
if GetCurrentResourceName() == resourceName then
|
if GetCurrentResourceName() == resourceName then
|
||||||
if isMenuOpen then
|
if isLicenseShowing then
|
||||||
closeLicense()
|
closeLicense()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if lib.getOpenContextMenu() then
|
||||||
|
lib.hideContext()
|
||||||
|
end
|
||||||
|
|
||||||
debugPrint("License-System Client gestoppt")
|
debugPrint("License-System Client gestoppt")
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
AddEventHandler('onResourceStart', function(resourceName)
|
||||||
|
if GetCurrentResourceName() == resourceName then
|
||||||
|
debugPrint("License-System Client gestartet")
|
||||||
|
|
||||||
|
-- Warten bis QBCore geladen ist
|
||||||
|
while not QBCore do
|
||||||
|
Wait(100)
|
||||||
|
end
|
||||||
|
|
||||||
|
debugPrint("QBCore erfolgreich geladen")
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Player laden Event
|
||||||
|
RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function()
|
||||||
|
debugPrint("Spieler geladen - License-System bereit")
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Job Update Event
|
||||||
|
RegisterNetEvent('QBCore:Client:OnJobUpdate', function(JobInfo)
|
||||||
|
debugPrint("Job aktualisiert: " .. JobInfo.name)
|
||||||
|
end)
|
||||||
|
|
||||||
-- Initialisierung
|
-- Initialisierung
|
||||||
CreateThread(function()
|
CreateThread(function()
|
||||||
debugPrint("License-System Client gestartet")
|
debugPrint("License-System Client Thread gestartet")
|
||||||
|
|
||||||
|
-- Warten bis Spieler gespawnt ist
|
||||||
|
while not NetworkIsPlayerActive(PlayerId()) do
|
||||||
|
Wait(100)
|
||||||
|
end
|
||||||
|
|
||||||
|
debugPrint("Spieler ist aktiv - System bereit")
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
|
|
@ -1,23 +1,28 @@
|
||||||
local QBCore = exports['qb-core']:GetCoreObject()
|
local QBCore = exports['qb-core']:GetCoreObject()
|
||||||
|
|
||||||
|
-- Lokale Variablen
|
||||||
|
local licenseCache = {}
|
||||||
|
|
||||||
-- Hilfsfunktionen
|
-- Hilfsfunktionen
|
||||||
local function debugPrint(message)
|
local function debugPrint(message)
|
||||||
if Config.Debug then
|
if Config.Debug then
|
||||||
print("^2[License-System] " .. message .. "^7")
|
print("^2[License-System Server] " .. message .. "^7")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function safeCallback(cb, ...)
|
local function safeCallback(cb, ...)
|
||||||
if cb and type(cb) == "function" then
|
if cb and type(cb) == "function" then
|
||||||
cb(...)
|
cb(...)
|
||||||
|
return true
|
||||||
else
|
else
|
||||||
debugPrint("^1Callback ist keine Funktion!^7")
|
debugPrint("^1FEHLER: Callback ist keine Funktion! Typ: " .. type(cb) .. "^7")
|
||||||
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function formatDate(date)
|
local function formatDate(timestamp)
|
||||||
if not date then return nil end
|
if not timestamp then return nil end
|
||||||
return os.date("%d.%m.%Y", date)
|
return os.date("%d.%m.%Y", timestamp)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function addDaysToDate(days)
|
local function addDaysToDate(days)
|
||||||
|
@ -26,13 +31,12 @@ end
|
||||||
|
|
||||||
local function isLicenseExpired(expireDate)
|
local function isLicenseExpired(expireDate)
|
||||||
if not expireDate then return false end
|
if not expireDate then return false end
|
||||||
return os.time() > expireDate
|
local expireTime = os.time({
|
||||||
end
|
year = tonumber(string.sub(expireDate, 7, 10)),
|
||||||
|
month = tonumber(string.sub(expireDate, 4, 5)),
|
||||||
local function getDaysUntilExpiry(expireDate)
|
day = tonumber(string.sub(expireDate, 1, 2))
|
||||||
if not expireDate then return nil end
|
})
|
||||||
local diff = expireDate - os.time()
|
return os.time() > expireTime
|
||||||
return math.ceil(diff / (24 * 60 * 60))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Spieler-Daten abrufen
|
-- Spieler-Daten abrufen
|
||||||
|
@ -43,6 +47,8 @@ local function getPlayerData(source)
|
||||||
return {
|
return {
|
||||||
citizenid = Player.PlayerData.citizenid,
|
citizenid = Player.PlayerData.citizenid,
|
||||||
name = Player.PlayerData.charinfo.firstname .. ' ' .. Player.PlayerData.charinfo.lastname,
|
name = Player.PlayerData.charinfo.firstname .. ' ' .. Player.PlayerData.charinfo.lastname,
|
||||||
|
firstname = Player.PlayerData.charinfo.firstname,
|
||||||
|
lastname = Player.PlayerData.charinfo.lastname,
|
||||||
birthday = Player.PlayerData.charinfo.birthdate,
|
birthday = Player.PlayerData.charinfo.birthdate,
|
||||||
gender = Player.PlayerData.charinfo.gender,
|
gender = Player.PlayerData.charinfo.gender,
|
||||||
job = Player.PlayerData.job.name,
|
job = Player.PlayerData.job.name,
|
||||||
|
@ -95,7 +101,10 @@ end
|
||||||
-- Lizenz erstellen
|
-- Lizenz erstellen
|
||||||
local function createLicense(citizenid, licenseType, issuedBy, classes)
|
local function createLicense(citizenid, licenseType, issuedBy, classes)
|
||||||
local licenseConfig = Config.LicenseTypes[licenseType]
|
local licenseConfig = Config.LicenseTypes[licenseType]
|
||||||
if not licenseConfig then return false end
|
if not licenseConfig then
|
||||||
|
debugPrint("^1Lizenz-Konfiguration nicht gefunden: " .. licenseType .. "^7")
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
local issueDate = os.time()
|
local issueDate = os.time()
|
||||||
local expireDate = nil
|
local expireDate = nil
|
||||||
|
@ -110,11 +119,13 @@ local function createLicense(citizenid, licenseType, issuedBy, classes)
|
||||||
issue_date = formatDate(issueDate),
|
issue_date = formatDate(issueDate),
|
||||||
expire_date = expireDate and formatDate(expireDate) or nil,
|
expire_date = expireDate and formatDate(expireDate) or nil,
|
||||||
issued_by = issuedBy,
|
issued_by = issuedBy,
|
||||||
is_active = true,
|
is_active = 1,
|
||||||
classes = classes and json.encode(classes) or '[]',
|
classes = classes and json.encode(classes) or '[]',
|
||||||
created_at = issueDate
|
created_at = issueDate
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debugPrint("Erstelle Lizenz: " .. licenseType .. " für " .. citizenid)
|
||||||
|
|
||||||
MySQL.Async.insert('INSERT INTO player_licenses (citizenid, license_type, issue_date, expire_date, issued_by, is_active, classes, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', {
|
MySQL.Async.insert('INSERT INTO player_licenses (citizenid, license_type, issue_date, expire_date, issued_by, is_active, classes, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', {
|
||||||
licenseData.citizenid,
|
licenseData.citizenid,
|
||||||
licenseData.license_type,
|
licenseData.license_type,
|
||||||
|
@ -126,35 +137,59 @@ local function createLicense(citizenid, licenseType, issuedBy, classes)
|
||||||
licenseData.created_at
|
licenseData.created_at
|
||||||
}, function(insertId)
|
}, function(insertId)
|
||||||
if insertId then
|
if insertId then
|
||||||
debugPrint("Lizenz erstellt: " .. licenseType .. " für " .. citizenid)
|
debugPrint("Lizenz erfolgreich erstellt mit ID: " .. insertId)
|
||||||
return true
|
-- Cache aktualisieren
|
||||||
|
if not licenseCache[citizenid] then
|
||||||
|
licenseCache[citizenid] = {}
|
||||||
|
end
|
||||||
|
licenseCache[citizenid][licenseType] = licenseData
|
||||||
else
|
else
|
||||||
debugPrint("^1Fehler beim Erstellen der Lizenz!^7")
|
debugPrint("^1Fehler beim Erstellen der Lizenz in der Datenbank!^7")
|
||||||
return false
|
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Aussteller-Name abrufen
|
||||||
|
local function getIssuerName(citizenid, callback)
|
||||||
|
if not citizenid then
|
||||||
|
callback('System')
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
MySQL.Async.fetchScalar('SELECT CONCAT(JSON_UNQUOTE(JSON_EXTRACT(charinfo, "$.firstname")), " ", JSON_UNQUOTE(JSON_EXTRACT(charinfo, "$.lastname"))) FROM players WHERE citizenid = ?', {
|
||||||
|
citizenid
|
||||||
|
}, function(issuerName)
|
||||||
|
callback(issuerName or 'Unbekannt')
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
-- Callbacks
|
-- Callbacks
|
||||||
QBCore.Functions.CreateCallback('license-system:server:getLicense', function(source, cb, targetId)
|
QBCore.Functions.CreateCallback('license-system:server:getLicense', function(source, cb, targetId)
|
||||||
debugPrint("getLicense aufgerufen für Spieler: " .. tostring(targetId))
|
debugPrint("getLicense Callback - Source: " .. source .. ", Target: " .. tostring(targetId))
|
||||||
|
|
||||||
|
if not cb or type(cb) ~= "function" then
|
||||||
|
debugPrint("^1FEHLER: Ungültiger Callback in getLicense!^7")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
local TargetPlayer = QBCore.Functions.GetPlayer(targetId)
|
local TargetPlayer = QBCore.Functions.GetPlayer(targetId)
|
||||||
if not TargetPlayer then
|
if not TargetPlayer then
|
||||||
debugPrint("^1Ziel-Spieler nicht gefunden!^7")
|
debugPrint("^1Ziel-Spieler nicht gefunden: " .. tostring(targetId) .. "^7")
|
||||||
safeCallback(cb, nil)
|
safeCallback(cb, nil)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local citizenid = TargetPlayer.PlayerData.citizenid
|
local citizenid = TargetPlayer.PlayerData.citizenid
|
||||||
|
debugPrint("Suche Lizenz für CitizenID: " .. citizenid)
|
||||||
|
|
||||||
MySQL.Async.fetchAll('SELECT * FROM player_licenses WHERE citizenid = ? AND is_active = TRUE ORDER BY created_at DESC LIMIT 1', {
|
MySQL.Async.fetchAll('SELECT * FROM player_licenses WHERE citizenid = ? AND is_active = 1 ORDER BY created_at DESC LIMIT 1', {
|
||||||
citizenid
|
citizenid
|
||||||
}, function(result)
|
}, function(result)
|
||||||
if result and result[1] then
|
if result and result[1] then
|
||||||
local license = result[1]
|
local license = result[1]
|
||||||
|
debugPrint("Lizenz gefunden: " .. license.license_type)
|
||||||
|
|
||||||
-- Spieler-Daten hinzufügen
|
-- Spieler-Daten hinzufügen
|
||||||
license.name = TargetPlayer.PlayerData.charinfo.firstname .. ' ' .. TargetPlayer.PlayerData.charinfo.lastname
|
license.name = TargetPlayer.PlayerData.charinfo.firstname .. ' ' .. TargetPlayer.PlayerData.charinfo.lastname
|
||||||
|
@ -162,61 +197,52 @@ QBCore.Functions.CreateCallback('license-system:server:getLicense', function(sou
|
||||||
license.gender = TargetPlayer.PlayerData.charinfo.gender
|
license.gender = TargetPlayer.PlayerData.charinfo.gender
|
||||||
|
|
||||||
-- Aussteller-Name abrufen
|
-- Aussteller-Name abrufen
|
||||||
if license.issued_by then
|
getIssuerName(license.issued_by, function(issuerName)
|
||||||
MySQL.Async.fetchScalar('SELECT CONCAT(JSON_UNQUOTE(JSON_EXTRACT(charinfo, "$.firstname")), " ", JSON_UNQUOTE(JSON_EXTRACT(charinfo, "$.lastname"))) FROM players WHERE citizenid = ?', {
|
license.issued_by_name = issuerName
|
||||||
license.issued_by
|
|
||||||
}, function(issuerName)
|
|
||||||
license.issued_by_name = issuerName or 'Unbekannt'
|
|
||||||
|
|
||||||
local licenseData = {
|
|
||||||
license = license,
|
|
||||||
config = Config.LicenseTypes[license.license_type] or {
|
|
||||||
label = license.license_type,
|
|
||||||
icon = 'fas fa-id-card'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
debugPrint("Lizenz gefunden: " .. license.license_type)
|
|
||||||
safeCallback(cb, licenseData)
|
|
||||||
end)
|
|
||||||
else
|
|
||||||
license.issued_by_name = 'System'
|
|
||||||
|
|
||||||
local licenseData = {
|
local licenseData = {
|
||||||
license = license,
|
license = license,
|
||||||
config = Config.LicenseTypes[license.license_type] or {
|
config = Config.LicenseTypes[license.license_type] or {
|
||||||
label = license.license_type,
|
label = license.license_type,
|
||||||
icon = 'fas fa-id-card'
|
icon = 'fas fa-id-card',
|
||||||
|
color = '#667eea'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
debugPrint("Lizenz gefunden: " .. license.license_type)
|
|
||||||
safeCallback(cb, licenseData)
|
safeCallback(cb, licenseData)
|
||||||
end
|
end)
|
||||||
else
|
else
|
||||||
debugPrint("Keine Lizenz gefunden für: " .. citizenid)
|
debugPrint("Keine aktive Lizenz gefunden für: " .. citizenid)
|
||||||
safeCallback(cb, nil)
|
safeCallback(cb, nil)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
QBCore.Functions.CreateCallback('license-system:server:getMyLicense', function(source, cb, licenseType)
|
QBCore.Functions.CreateCallback('license-system:server:getMyLicense', function(source, cb, licenseType)
|
||||||
debugPrint("getMyLicense aufgerufen für Typ: " .. tostring(licenseType))
|
debugPrint("getMyLicense Callback - Source: " .. source .. ", Typ: " .. tostring(licenseType))
|
||||||
|
|
||||||
|
if not cb or type(cb) ~= "function" then
|
||||||
|
debugPrint("^1FEHLER: Ungültiger Callback in getMyLicense!^7")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
local Player = QBCore.Functions.GetPlayer(source)
|
local Player = QBCore.Functions.GetPlayer(source)
|
||||||
if not Player then
|
if not Player then
|
||||||
|
debugPrint("^1Spieler nicht gefunden: " .. source .. "^7")
|
||||||
safeCallback(cb, nil)
|
safeCallback(cb, nil)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local citizenid = Player.PlayerData.citizenid
|
local citizenid = Player.PlayerData.citizenid
|
||||||
|
debugPrint("Suche eigene Lizenz - CitizenID: " .. citizenid .. ", Typ: " .. licenseType)
|
||||||
|
|
||||||
MySQL.Async.fetchAll('SELECT * FROM player_licenses WHERE citizenid = ? AND license_type = ? AND is_active = TRUE ORDER BY created_at DESC LIMIT 1', {
|
MySQL.Async.fetchAll('SELECT * FROM player_licenses WHERE citizenid = ? AND license_type = ? AND is_active = 1 ORDER BY created_at DESC LIMIT 1', {
|
||||||
citizenid,
|
citizenid,
|
||||||
licenseType
|
licenseType
|
||||||
}, function(result)
|
}, function(result)
|
||||||
if result and result[1] then
|
if result and result[1] then
|
||||||
local license = result[1]
|
local license = result[1]
|
||||||
|
debugPrint("Eigene Lizenz gefunden: " .. license.license_type)
|
||||||
|
|
||||||
-- Spieler-Daten hinzufügen
|
-- Spieler-Daten hinzufügen
|
||||||
license.name = Player.PlayerData.charinfo.firstname .. ' ' .. Player.PlayerData.charinfo.lastname
|
license.name = Player.PlayerData.charinfo.firstname .. ' ' .. Player.PlayerData.charinfo.lastname
|
||||||
|
@ -224,65 +250,59 @@ QBCore.Functions.CreateCallback('license-system:server:getMyLicense', function(s
|
||||||
license.gender = Player.PlayerData.charinfo.gender
|
license.gender = Player.PlayerData.charinfo.gender
|
||||||
|
|
||||||
-- Aussteller-Name abrufen
|
-- Aussteller-Name abrufen
|
||||||
if license.issued_by then
|
getIssuerName(license.issued_by, function(issuerName)
|
||||||
MySQL.Async.fetchScalar('SELECT CONCAT(JSON_UNQUOTE(JSON_EXTRACT(charinfo, "$.firstname")), " ", JSON_UNQUOTE(JSON_EXTRACT(charinfo, "$.lastname"))) FROM players WHERE citizenid = ?', {
|
license.issued_by_name = issuerName
|
||||||
license.issued_by
|
|
||||||
}, function(issuerName)
|
|
||||||
license.issued_by_name = issuerName or 'Unbekannt'
|
|
||||||
|
|
||||||
local licenseData = {
|
|
||||||
license = license,
|
|
||||||
config = Config.LicenseTypes[license.license_type] or {
|
|
||||||
label = license.license_type,
|
|
||||||
icon = 'fas fa-id-card'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
safeCallback(cb, licenseData)
|
|
||||||
end)
|
|
||||||
else
|
|
||||||
license.issued_by_name = 'System'
|
|
||||||
|
|
||||||
local licenseData = {
|
local licenseData = {
|
||||||
license = license,
|
license = license,
|
||||||
config = Config.LicenseTypes[license.license_type] or {
|
config = Config.LicenseTypes[license.license_type] or {
|
||||||
label = license.license_type,
|
label = license.license_type,
|
||||||
icon = 'fas fa-id-card'
|
icon = 'fas fa-id-card',
|
||||||
|
color = '#667eea'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
safeCallback(cb, licenseData)
|
safeCallback(cb, licenseData)
|
||||||
end
|
end)
|
||||||
else
|
else
|
||||||
debugPrint("Keine Lizenz vom Typ " .. licenseType .. " gefunden")
|
debugPrint("Keine eigene Lizenz vom Typ " .. licenseType .. " gefunden")
|
||||||
safeCallback(cb, nil)
|
safeCallback(cb, nil)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
QBCore.Functions.CreateCallback('license-system:server:getPlayerLicenses', function(source, cb, targetId)
|
QBCore.Functions.CreateCallback('license-system:server:getPlayerLicenses', function(source, cb, targetId)
|
||||||
debugPrint("getPlayerLicenses aufgerufen für Spieler: " .. tostring(targetId))
|
debugPrint("getPlayerLicenses Callback - Source: " .. source .. ", Target: " .. tostring(targetId))
|
||||||
|
|
||||||
|
if not cb or type(cb) ~= "function" then
|
||||||
|
debugPrint("^1FEHLER: Ungültiger Callback in getPlayerLicenses!^7")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
local TargetPlayer = QBCore.Functions.GetPlayer(targetId)
|
local TargetPlayer = QBCore.Functions.GetPlayer(targetId)
|
||||||
if not TargetPlayer then
|
if not TargetPlayer then
|
||||||
|
debugPrint("^1Ziel-Spieler nicht gefunden: " .. tostring(targetId) .. "^7")
|
||||||
safeCallback(cb, {})
|
safeCallback(cb, {})
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local citizenid = TargetPlayer.PlayerData.citizenid
|
local citizenid = TargetPlayer.PlayerData.citizenid
|
||||||
|
debugPrint("Suche alle Lizenzen für CitizenID: " .. citizenid)
|
||||||
|
|
||||||
MySQL.Async.fetchAll('SELECT * FROM player_licenses WHERE citizenid = ? ORDER BY created_at DESC', {
|
MySQL.Async.fetchAll('SELECT * FROM player_licenses WHERE citizenid = ? ORDER BY created_at DESC', {
|
||||||
citizenid
|
citizenid
|
||||||
}, function(result)
|
}, function(result)
|
||||||
if result then
|
if result then
|
||||||
|
debugPrint("Gefundene Lizenzen: " .. #result)
|
||||||
|
|
||||||
-- Spieler-Daten zu jeder Lizenz hinzufügen
|
-- Spieler-Daten zu jeder Lizenz hinzufügen
|
||||||
for i, license in ipairs(result) do
|
for i, license in ipairs(result) do
|
||||||
license.name = TargetPlayer.PlayerData.charinfo.firstname .. ' ' .. TargetPlayer.PlayerData.charinfo.lastname
|
license.name = TargetPlayer.PlayerData.charinfo.firstname .. ' ' .. TargetPlayer.PlayerData.charinfo.lastname
|
||||||
license.birthday = TargetPlayer.PlayerData.charinfo.birthdate
|
license.birthday = TargetPlayer.PlayerData.charinfo.birthdate
|
||||||
license.gender = TargetPlayer.PlayerData.charinfo.gender
|
license.gender = TargetPlayer.PlayerData.charinfo.gender
|
||||||
|
license.issued_by_name = 'System' -- Wird später durch echten Namen ersetzt
|
||||||
end
|
end
|
||||||
|
|
||||||
debugPrint("Gefundene Lizenzen: " .. #result)
|
|
||||||
safeCallback(cb, result)
|
safeCallback(cb, result)
|
||||||
else
|
else
|
||||||
debugPrint("Keine Lizenzen gefunden")
|
debugPrint("Keine Lizenzen gefunden")
|
||||||
|
@ -292,13 +312,24 @@ QBCore.Functions.CreateCallback('license-system:server:getPlayerLicenses', funct
|
||||||
end)
|
end)
|
||||||
|
|
||||||
QBCore.Functions.CreateCallback('license-system:server:canIssueLicense', function(source, cb, licenseType)
|
QBCore.Functions.CreateCallback('license-system:server:canIssueLicense', function(source, cb, licenseType)
|
||||||
|
debugPrint("canIssueLicense Callback - Source: " .. source .. ", Typ: " .. tostring(licenseType))
|
||||||
|
|
||||||
|
if not cb or type(cb) ~= "function" then
|
||||||
|
debugPrint("^1FEHLER: Ungültiger Callback in canIssueLicense!^7")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
local hasAuth = hasPermission(source, licenseType)
|
local hasAuth = hasPermission(source, licenseType)
|
||||||
|
debugPrint("Berechtigung für Lizenz " .. licenseType .. ": " .. tostring(hasAuth))
|
||||||
|
|
||||||
safeCallback(cb, hasAuth)
|
safeCallback(cb, hasAuth)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- Events
|
-- Events
|
||||||
RegisterNetEvent('license-system:server:issueLicense', function(targetId, licenseType, classes)
|
RegisterNetEvent('license-system:server:issueLicense', function(targetId, licenseType, classes)
|
||||||
local src = source
|
local src = source
|
||||||
|
debugPrint("Event: issueLicense - Von: " .. src .. ", Für: " .. targetId .. ", Typ: " .. licenseType)
|
||||||
|
|
||||||
local Player = QBCore.Functions.GetPlayer(src)
|
local Player = QBCore.Functions.GetPlayer(src)
|
||||||
local TargetPlayer = QBCore.Functions.GetPlayer(targetId)
|
local TargetPlayer = QBCore.Functions.GetPlayer(targetId)
|
||||||
|
|
||||||
|
@ -335,13 +366,16 @@ RegisterNetEvent('license-system:server:issueLicense', function(targetId, licens
|
||||||
|
|
||||||
-- Geld abziehen
|
-- Geld abziehen
|
||||||
TargetPlayer.Functions.RemoveMoney('cash', licenseConfig.price, 'license-fee')
|
TargetPlayer.Functions.RemoveMoney('cash', licenseConfig.price, 'license-fee')
|
||||||
|
debugPrint("Geld abgezogen: " .. licenseConfig.price .. "$ von " .. TargetPlayer.PlayerData.charinfo.firstname)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Alte Lizenz deaktivieren
|
-- Alte Lizenz deaktivieren
|
||||||
MySQL.Async.execute('UPDATE player_licenses SET is_active = FALSE WHERE citizenid = ? AND license_type = ?', {
|
MySQL.Async.execute('UPDATE player_licenses SET is_active = 0 WHERE citizenid = ? AND license_type = ?', {
|
||||||
TargetPlayer.PlayerData.citizenid,
|
TargetPlayer.PlayerData.citizenid,
|
||||||
licenseType
|
licenseType
|
||||||
})
|
}, function(affectedRows)
|
||||||
|
debugPrint("Alte Lizenzen deaktiviert: " .. affectedRows)
|
||||||
|
end)
|
||||||
|
|
||||||
-- Neue Lizenz erstellen
|
-- Neue Lizenz erstellen
|
||||||
local success = createLicense(TargetPlayer.PlayerData.citizenid, licenseType, Player.PlayerData.citizenid, classes)
|
local success = createLicense(TargetPlayer.PlayerData.citizenid, licenseType, Player.PlayerData.citizenid, classes)
|
||||||
|
@ -359,6 +393,8 @@ end)
|
||||||
|
|
||||||
RegisterNetEvent('license-system:server:revokeLicense', function(targetId, licenseType)
|
RegisterNetEvent('license-system:server:revokeLicense', function(targetId, licenseType)
|
||||||
local src = source
|
local src = source
|
||||||
|
debugPrint("Event: revokeLicense - Von: " .. src .. ", Für: " .. targetId .. ", Typ: " .. licenseType)
|
||||||
|
|
||||||
local Player = QBCore.Functions.GetPlayer(src)
|
local Player = QBCore.Functions.GetPlayer(src)
|
||||||
local TargetPlayer = QBCore.Functions.GetPlayer(targetId)
|
local TargetPlayer = QBCore.Functions.GetPlayer(targetId)
|
||||||
|
|
||||||
|
@ -374,16 +410,20 @@ RegisterNetEvent('license-system:server:revokeLicense', function(targetId, licen
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Lizenz deaktivieren
|
-- Lizenz deaktivieren
|
||||||
MySQL.Async.execute('UPDATE player_licenses SET is_active = FALSE WHERE citizenid = ? AND license_type = ? AND is_active = TRUE', {
|
MySQL.Async.execute('UPDATE player_licenses SET is_active = 0 WHERE citizenid = ? AND license_type = ? AND is_active = 1', {
|
||||||
TargetPlayer.PlayerData.citizenid,
|
TargetPlayer.PlayerData.citizenid,
|
||||||
licenseType
|
licenseType
|
||||||
}, function(affectedRows)
|
}, function(affectedRows)
|
||||||
if affectedRows > 0 then
|
if affectedRows > 0 then
|
||||||
TriggerClientEvent('QBCore:Notify', src, Config.Notifications.license_revoked.message, Config.Notifications.license_revoked.type)
|
TriggerClientEvent('QBCore:Notify', src, Config.Notifications.license_revoked.message, Config.Notifications.license_revoked.type)
|
||||||
TriggerClientEvent('QBCore:Notify', targetId, 'Deine ' .. (Config.LicenseTypes[licenseType]?.label or licenseType) .. ' wurde entzogen!', 'error')
|
TriggerClientEvent('QBCore:Notify', targetId, 'Deine ' .. (Config.LicenseTypes[licenseType] and Config.LicenseTypes[licenseType].label or licenseType) .. ' wurde entzogen!', 'error')
|
||||||
|
|
||||||
-- Log erstellen
|
-- Cache aktualisieren
|
||||||
debugPrint(Player.PlayerData.charinfo.firstname .. ' ' .. Player.PlayerData.charinfo.lastname .. ' hat ' .. TargetPlayer.PlayerData.charinfo.firstname .. ' ' .. TargetPlayer.PlayerData.charinfo.lastname .. ' die ' .. (Config.LicenseTypes[licenseType]?.label or licenseType) .. ' entzogen')
|
if licenseCache[TargetPlayer.PlayerData.citizenid] then
|
||||||
|
licenseCache[TargetPlayer.PlayerData.citizenid][licenseType] = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
debugPrint(Player.PlayerData.charinfo.firstname .. ' ' .. Player.PlayerData.charinfo.lastname .. ' hat ' .. TargetPlayer.PlayerData.charinfo.firstname .. ' ' .. TargetPlayer.PlayerData.charinfo.lastname .. ' die ' .. (Config.LicenseTypes[licenseType] and Config.LicenseTypes[licenseType].label or licenseType) .. ' entzogen')
|
||||||
else
|
else
|
||||||
TriggerClientEvent('QBCore:Notify', src, 'Keine aktive Lizenz gefunden!', 'error')
|
TriggerClientEvent('QBCore:Notify', src, 'Keine aktive Lizenz gefunden!', 'error')
|
||||||
end
|
end
|
||||||
|
@ -392,12 +432,13 @@ end)
|
||||||
|
|
||||||
RegisterNetEvent('license-system:server:savePhoto', function(citizenid, photoData)
|
RegisterNetEvent('license-system:server:savePhoto', function(citizenid, photoData)
|
||||||
local src = source
|
local src = source
|
||||||
local Player = QBCore.Functions.GetPlayer(src)
|
debugPrint("Event: savePhoto für CitizenID: " .. citizenid)
|
||||||
|
|
||||||
|
local Player = QBCore.Functions.GetPlayer(src)
|
||||||
if not Player then return end
|
if not Player then return end
|
||||||
|
|
||||||
-- Foto in der Datenbank speichern
|
-- Foto in der Datenbank speichern
|
||||||
MySQL.Async.execute('UPDATE player_licenses SET photo_url = ? WHERE citizenid = ? AND is_active = TRUE', {
|
MySQL.Async.execute('UPDATE player_licenses SET photo_url = ? WHERE citizenid = ? AND is_active = 1', {
|
||||||
photoData,
|
photoData,
|
||||||
citizenid
|
citizenid
|
||||||
}, function(affectedRows)
|
}, function(affectedRows)
|
||||||
|
@ -420,6 +461,8 @@ QBCore.Commands.Add('givelicense', 'Lizenz an Spieler vergeben', {
|
||||||
local licenseType = args[2]
|
local licenseType = args[2]
|
||||||
local classes = args[3] and {args[3]} or nil
|
local classes = args[3] and {args[3]} or nil
|
||||||
|
|
||||||
|
debugPrint("Admin-Command: givelicense - ID: " .. tostring(targetId) .. ", Typ: " .. tostring(licenseType))
|
||||||
|
|
||||||
if not targetId or not licenseType then
|
if not targetId or not licenseType then
|
||||||
TriggerClientEvent('QBCore:Notify', source, 'Verwendung: /givelicense [id] [typ] [klassen]', 'error')
|
TriggerClientEvent('QBCore:Notify', source, 'Verwendung: /givelicense [id] [typ] [klassen]', 'error')
|
||||||
return
|
return
|
||||||
|
@ -440,6 +483,8 @@ QBCore.Commands.Add('revokelicense', 'Lizenz entziehen', {
|
||||||
local targetId = tonumber(args[1])
|
local targetId = tonumber(args[1])
|
||||||
local licenseType = args[2]
|
local licenseType = args[2]
|
||||||
|
|
||||||
|
debugPrint("Admin-Command: revokelicense - ID: " .. tostring(targetId) .. ", Typ: " .. tostring(licenseType))
|
||||||
|
|
||||||
if not targetId or not licenseType then
|
if not targetId or not licenseType then
|
||||||
TriggerClientEvent('QBCore:Notify', source, 'Verwendung: /revokelicense [id] [typ]', 'error')
|
TriggerClientEvent('QBCore:Notify', source, 'Verwendung: /revokelicense [id] [typ]', 'error')
|
||||||
return
|
return
|
||||||
|
@ -456,7 +501,7 @@ if Config.Database.auto_cleanup then
|
||||||
|
|
||||||
local cutoffDate = os.time() - (Config.Database.cleanup_days * 24 * 60 * 60)
|
local cutoffDate = os.time() - (Config.Database.cleanup_days * 24 * 60 * 60)
|
||||||
|
|
||||||
MySQL.Async.execute('DELETE FROM player_licenses WHERE is_active = FALSE AND created_at < ?', {
|
MySQL.Async.execute('DELETE FROM player_licenses WHERE is_active = 0 AND created_at < ?', {
|
||||||
cutoffDate
|
cutoffDate
|
||||||
}, function(affectedRows)
|
}, function(affectedRows)
|
||||||
if affectedRows > 0 then
|
if affectedRows > 0 then
|
||||||
|
@ -472,18 +517,12 @@ CreateThread(function()
|
||||||
while true do
|
while true do
|
||||||
Wait(60 * 60 * 1000) -- Jede Stunde
|
Wait(60 * 60 * 1000) -- Jede Stunde
|
||||||
|
|
||||||
MySQL.Async.fetchAll('SELECT * FROM player_licenses WHERE is_active = TRUE AND expire_date IS NOT NULL', {}, function(result)
|
MySQL.Async.fetchAll('SELECT * FROM player_licenses WHERE is_active = 1 AND expire_date IS NOT NULL', {}, function(result)
|
||||||
if result then
|
if result then
|
||||||
for _, license in ipairs(result) do
|
for _, license in ipairs(result) do
|
||||||
local expireTime = os.time({
|
if isLicenseExpired(license.expire_date) then
|
||||||
year = tonumber(string.sub(license.expire_date, 7, 10)),
|
|
||||||
month = tonumber(string.sub(license.expire_date, 4, 5)),
|
|
||||||
day = tonumber(string.sub(license.expire_date, 1, 2))
|
|
||||||
})
|
|
||||||
|
|
||||||
if isLicenseExpired(expireTime) then
|
|
||||||
-- Lizenz als abgelaufen markieren
|
-- Lizenz als abgelaufen markieren
|
||||||
MySQL.Async.execute('UPDATE player_licenses SET is_active = FALSE WHERE id = ?', {
|
MySQL.Async.execute('UPDATE player_licenses SET is_active = 0 WHERE id = ?', {
|
||||||
license.id
|
license.id
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -509,7 +548,7 @@ AddEventHandler('onResourceStart', function(resourceName)
|
||||||
issue_date VARCHAR(20) NOT NULL,
|
issue_date VARCHAR(20) NOT NULL,
|
||||||
expire_date VARCHAR(20) NULL,
|
expire_date VARCHAR(20) NULL,
|
||||||
issued_by VARCHAR(50) NULL,
|
issued_by VARCHAR(50) NULL,
|
||||||
is_active BOOLEAN DEFAULT TRUE,
|
is_active TINYINT(1) DEFAULT 1,
|
||||||
classes TEXT NULL,
|
classes TEXT NULL,
|
||||||
photo_url TEXT NULL,
|
photo_url TEXT NULL,
|
||||||
notes TEXT NULL,
|
notes TEXT NULL,
|
||||||
|
@ -519,12 +558,20 @@ AddEventHandler('onResourceStart', function(resourceName)
|
||||||
INDEX idx_license_type (license_type),
|
INDEX idx_license_type (license_type),
|
||||||
INDEX idx_active (is_active)
|
INDEX idx_active (is_active)
|
||||||
)
|
)
|
||||||
]])
|
]], {}, function(success)
|
||||||
|
if success then
|
||||||
|
debugPrint("Datenbank-Tabelle erfolgreich erstellt/überprüft")
|
||||||
|
else
|
||||||
|
debugPrint("^1Fehler beim Erstellen der Datenbank-Tabelle!^7")
|
||||||
|
end
|
||||||
|
end)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
AddEventHandler('onResourceStop', function(resourceName)
|
AddEventHandler('onResourceStop', function(resourceName)
|
||||||
if GetCurrentResourceName() == resourceName then
|
if GetCurrentResourceName() == resourceName then
|
||||||
debugPrint("License-System Server gestoppt")
|
debugPrint("License-System Server gestoppt")
|
||||||
|
-- Cache leeren
|
||||||
|
licenseCache = {}
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue