2025-08-04 06:14:47 +02:00
local QBCore = exports [ ' qb-core ' ] : GetCoreObject ( )
2025-08-04 08:12:36 +02:00
-- Lokale Variablen
local licenseCache = { }
2025-08-04 07:40:06 +02:00
-- Hilfsfunktionen
local function debugPrint ( message )
if Config.Debug then
2025-08-04 08:12:36 +02:00
print ( " ^2[License-System Server] " .. message .. " ^7 " )
2025-08-04 07:40:06 +02:00
end
end
2025-08-04 06:14:47 +02:00
2025-08-04 08:12:36 +02:00
local function formatDate ( timestamp )
if not timestamp then return nil end
return os.date ( " %d.%m.%Y " , timestamp )
2025-08-04 07:40:06 +02:00
end
2025-08-04 06:14:47 +02:00
2025-08-04 07:40:06 +02:00
local function addDaysToDate ( days )
return os.time ( ) + ( days * 24 * 60 * 60 )
end
2025-08-04 06:14:47 +02:00
2025-08-04 07:40:06 +02:00
local function isLicenseExpired ( expireDate )
if not expireDate then return false end
2025-08-04 08:12:36 +02:00
local expireTime = os.time ( {
year = tonumber ( string.sub ( expireDate , 7 , 10 ) ) ,
month = tonumber ( string.sub ( expireDate , 4 , 5 ) ) ,
day = tonumber ( string.sub ( expireDate , 1 , 2 ) )
} )
return os.time ( ) > expireTime
2025-08-04 07:40:06 +02:00
end
2025-08-04 06:14:47 +02:00
2025-08-04 07:40:06 +02:00
-- Spieler-Daten abrufen
local function getPlayerData ( source )
local Player = QBCore.Functions . GetPlayer ( source )
if not Player then return nil end
return {
citizenid = Player.PlayerData . citizenid ,
name = Player.PlayerData . charinfo.firstname .. ' ' .. Player.PlayerData . charinfo.lastname ,
2025-08-04 08:12:36 +02:00
firstname = Player.PlayerData . charinfo.firstname ,
lastname = Player.PlayerData . charinfo.lastname ,
2025-08-04 07:40:06 +02:00
birthday = Player.PlayerData . charinfo.birthdate ,
gender = Player.PlayerData . charinfo.gender ,
job = Player.PlayerData . job.name ,
money = Player.PlayerData . money.cash
}
end
2025-08-04 06:14:47 +02:00
2025-08-04 07:40:06 +02:00
-- Berechtigung prüfen
local function hasPermission ( source , licenseType )
local playerData = getPlayerData ( source )
if not playerData then return false end
-- Admin-Check
if QBCore.Functions . HasPermission ( source , ' admin ' ) then
return true
end
-- Job-Check
if Config.AuthorizedJobs [ playerData.job ] then
return true
end
-- Spezifische Lizenz-Berechtigung
local licenseConfig = Config.LicenseTypes [ licenseType ]
if licenseConfig and licenseConfig.required_job then
return playerData.job == licenseConfig.required_job
end
2025-08-04 06:14:47 +02:00
2025-08-04 07:40:06 +02:00
return false
end
2025-08-04 06:14:47 +02:00
2025-08-04 07:40:06 +02:00
-- Benötigte Items prüfen
local function hasRequiredItems ( source , licenseType )
local Player = QBCore.Functions . GetPlayer ( source )
if not Player then return false end
local licenseConfig = Config.LicenseTypes [ licenseType ]
if not licenseConfig or not licenseConfig.required_items then return true end
for _ , item in ipairs ( licenseConfig.required_items ) do
local hasItem = Player.Functions . GetItemByName ( item )
if not hasItem or hasItem.amount < 1 then
return false
end
2025-08-04 06:14:47 +02:00
end
2025-08-04 07:40:06 +02:00
return true
end
2025-08-04 06:14:47 +02:00
2025-08-04 07:40:06 +02:00
-- Lizenz erstellen
local function createLicense ( citizenid , licenseType , issuedBy , classes )
local licenseConfig = Config.LicenseTypes [ licenseType ]
2025-08-04 08:12:36 +02:00
if not licenseConfig then
debugPrint ( " ^1Lizenz-Konfiguration nicht gefunden: " .. licenseType .. " ^7 " )
return false
end
2025-08-04 07:40:06 +02:00
local issueDate = os.time ( )
local expireDate = nil
if licenseConfig.can_expire and licenseConfig.validity_days then
expireDate = addDaysToDate ( licenseConfig.validity_days )
end
local licenseData = {
citizenid = citizenid ,
license_type = licenseType ,
issue_date = formatDate ( issueDate ) ,
expire_date = expireDate and formatDate ( expireDate ) or nil ,
issued_by = issuedBy ,
2025-08-04 08:12:36 +02:00
is_active = 1 ,
2025-08-04 07:40:06 +02:00
classes = classes and json.encode ( classes ) or ' [] ' ,
created_at = issueDate
}
2025-08-04 08:12:36 +02:00
debugPrint ( " Erstelle Lizenz: " .. licenseType .. " für " .. citizenid )
2025-08-04 07:40:06 +02:00
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.license_type ,
2025-08-04 06:14:47 +02:00
licenseData.issue_date ,
licenseData.expire_date ,
2025-08-04 07:40:06 +02:00
licenseData.issued_by ,
licenseData.is_active ,
licenseData.classes ,
licenseData.created_at
2025-08-04 06:14:47 +02:00
} , function ( insertId )
if insertId then
2025-08-04 08:12:36 +02:00
debugPrint ( " Lizenz erfolgreich erstellt mit ID: " .. insertId )
-- Cache aktualisieren
if not licenseCache [ citizenid ] then
licenseCache [ citizenid ] = { }
end
licenseCache [ citizenid ] [ licenseType ] = licenseData
2025-08-04 06:14:47 +02:00
else
2025-08-04 08:12:36 +02:00
debugPrint ( " ^1Fehler beim Erstellen der Lizenz in der Datenbank!^7 " )
2025-08-04 06:14:47 +02:00
end
end )
2025-08-04 07:40:06 +02:00
return true
end
2025-08-04 06:14:47 +02:00
2025-08-04 08:12:36 +02:00
-- 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
2025-08-04 08:31:45 +02:00
-- EVENT: Einzelne Lizenz abrufen
RegisterNetEvent ( ' license-system:server:requestLicense ' , function ( targetId )
local src = source
debugPrint ( " === Event: requestLicense === " )
debugPrint ( " Source: " .. src .. " , Target: " .. tostring ( targetId ) )
2025-08-04 07:40:06 +02:00
local TargetPlayer = QBCore.Functions . GetPlayer ( targetId )
if not TargetPlayer then
2025-08-04 08:12:36 +02:00
debugPrint ( " ^1Ziel-Spieler nicht gefunden: " .. tostring ( targetId ) .. " ^7 " )
2025-08-04 08:31:45 +02:00
TriggerClientEvent ( ' license-system:client:receiveLicense ' , src , nil )
2025-08-04 06:14:47 +02:00
return
end
2025-08-04 07:40:06 +02:00
local citizenid = TargetPlayer.PlayerData . citizenid
2025-08-04 08:12:36 +02:00
debugPrint ( " Suche Lizenz für CitizenID: " .. citizenid )
2025-08-04 07:40:06 +02:00
2025-08-04 08:12:36 +02:00
MySQL.Async . fetchAll ( ' SELECT * FROM player_licenses WHERE citizenid = ? AND is_active = 1 ORDER BY created_at DESC LIMIT 1 ' , {
2025-08-04 07:40:06 +02:00
citizenid
} , function ( result )
if result and result [ 1 ] then
local license = result [ 1 ]
2025-08-04 08:12:36 +02:00
debugPrint ( " Lizenz gefunden: " .. license.license_type )
2025-08-04 07:40:06 +02:00
-- Spieler-Daten hinzufügen
license.name = TargetPlayer.PlayerData . charinfo.firstname .. ' ' .. TargetPlayer.PlayerData . charinfo.lastname
license.birthday = TargetPlayer.PlayerData . charinfo.birthdate
license.gender = TargetPlayer.PlayerData . charinfo.gender
-- Aussteller-Name abrufen
2025-08-04 08:12:36 +02:00
getIssuerName ( license.issued_by , function ( issuerName )
license.issued_by_name = issuerName
2025-08-04 07:40:06 +02:00
local licenseData = {
license = license ,
config = Config.LicenseTypes [ license.license_type ] or {
label = license.license_type ,
2025-08-04 08:12:36 +02:00
icon = ' fas fa-id-card ' ,
color = ' #667eea '
2025-08-04 07:40:06 +02:00
}
}
2025-08-04 08:31:45 +02:00
debugPrint ( " Sende Lizenz-Daten an Client " )
TriggerClientEvent ( ' license-system:client:receiveLicense ' , src , licenseData )
2025-08-04 08:12:36 +02:00
end )
2025-08-04 06:14:47 +02:00
else
2025-08-04 08:12:36 +02:00
debugPrint ( " Keine aktive Lizenz gefunden für: " .. citizenid )
2025-08-04 08:31:45 +02:00
TriggerClientEvent ( ' license-system:client:receiveLicense ' , src , nil )
2025-08-04 06:14:47 +02:00
end
end )
end )
2025-08-04 08:31:45 +02:00
-- EVENT: Eigene Lizenz abrufen
RegisterNetEvent ( ' license-system:server:requestMyLicense ' , function ( licenseType )
local src = source
debugPrint ( " === Event: requestMyLicense === " )
debugPrint ( " Source: " .. src .. " , LicenseType: " .. tostring ( licenseType ) )
2025-08-04 06:14:47 +02:00
2025-08-04 08:31:45 +02:00
local Player = QBCore.Functions . GetPlayer ( src )
2025-08-04 07:40:06 +02:00
if not Player then
2025-08-04 08:31:45 +02:00
debugPrint ( " ^1Spieler nicht gefunden: " .. src .. " ^7 " )
TriggerClientEvent ( ' license-system:client:receiveMyLicense ' , src , nil , licenseType )
2025-08-04 06:14:47 +02:00
return
end
2025-08-04 07:40:06 +02:00
local citizenid = Player.PlayerData . citizenid
2025-08-04 08:12:36 +02:00
debugPrint ( " Suche eigene Lizenz - CitizenID: " .. citizenid .. " , Typ: " .. licenseType )
2025-08-04 07:40:06 +02:00
2025-08-04 08:12:36 +02:00
MySQL.Async . fetchAll ( ' SELECT * FROM player_licenses WHERE citizenid = ? AND license_type = ? AND is_active = 1 ORDER BY created_at DESC LIMIT 1 ' , {
2025-08-04 07:40:06 +02:00
citizenid ,
licenseType
} , function ( result )
if result and result [ 1 ] then
local license = result [ 1 ]
2025-08-04 08:12:36 +02:00
debugPrint ( " Eigene Lizenz gefunden: " .. license.license_type )
2025-08-04 07:40:06 +02:00
-- Spieler-Daten hinzufügen
license.name = Player.PlayerData . charinfo.firstname .. ' ' .. Player.PlayerData . charinfo.lastname
license.birthday = Player.PlayerData . charinfo.birthdate
license.gender = Player.PlayerData . charinfo.gender
-- Aussteller-Name abrufen
2025-08-04 08:12:36 +02:00
getIssuerName ( license.issued_by , function ( issuerName )
license.issued_by_name = issuerName
2025-08-04 07:40:06 +02:00
local licenseData = {
license = license ,
config = Config.LicenseTypes [ license.license_type ] or {
label = license.license_type ,
2025-08-04 08:12:36 +02:00
icon = ' fas fa-id-card ' ,
color = ' #667eea '
2025-08-04 07:40:06 +02:00
}
}
2025-08-04 08:31:45 +02:00
debugPrint ( " Sende eigene Lizenz-Daten an Client " )
TriggerClientEvent ( ' license-system:client:receiveMyLicense ' , src , licenseData , licenseType )
2025-08-04 08:12:36 +02:00
end )
2025-08-04 06:14:47 +02:00
else
2025-08-04 08:12:36 +02:00
debugPrint ( " Keine eigene Lizenz vom Typ " .. licenseType .. " gefunden " )
2025-08-04 08:31:45 +02:00
TriggerClientEvent ( ' license-system:client:receiveMyLicense ' , src , nil , licenseType )
2025-08-04 06:14:47 +02:00
end
end )
end )
2025-08-04 08:31:45 +02:00
-- EVENT: Alle Spieler-Lizenzen abrufen
RegisterNetEvent ( ' license-system:server:requestPlayerLicenses ' , function ( targetId )
local src = source
debugPrint ( " === Event: requestPlayerLicenses === " )
debugPrint ( " Source: " .. src .. " , Target: " .. tostring ( targetId ) )
2025-08-04 07:40:06 +02:00
local TargetPlayer = QBCore.Functions . GetPlayer ( targetId )
if not TargetPlayer then
2025-08-04 08:12:36 +02:00
debugPrint ( " ^1Ziel-Spieler nicht gefunden: " .. tostring ( targetId ) .. " ^7 " )
2025-08-04 08:31:45 +02:00
TriggerClientEvent ( ' license-system:client:receivePlayerLicenses ' , src , { } , targetId , " Unbekannt " )
2025-08-04 07:40:06 +02:00
return
2025-08-04 06:14:47 +02:00
end
2025-08-04 07:40:06 +02:00
local citizenid = TargetPlayer.PlayerData . citizenid
2025-08-04 08:31:45 +02:00
local targetName = TargetPlayer.PlayerData . charinfo.firstname .. ' ' .. TargetPlayer.PlayerData . charinfo.lastname
2025-08-04 08:12:36 +02:00
debugPrint ( " Suche alle Lizenzen für CitizenID: " .. citizenid )
2025-08-04 07:40:06 +02:00
MySQL.Async . fetchAll ( ' SELECT * FROM player_licenses WHERE citizenid = ? ORDER BY created_at DESC ' , {
citizenid
} , function ( result )
2025-08-04 08:31:45 +02:00
local licenses = result or { }
debugPrint ( " Gefundene Lizenzen: " .. # licenses )
-- Spieler-Daten zu jeder Lizenz hinzufügen
for i , license in ipairs ( licenses ) do
license.name = TargetPlayer.PlayerData . charinfo.firstname .. ' ' .. TargetPlayer.PlayerData . charinfo.lastname
license.birthday = TargetPlayer.PlayerData . charinfo.birthdate
license.gender = TargetPlayer.PlayerData . charinfo.gender
license.issued_by_name = ' System ' -- Wird später durch echten Namen ersetzt
2025-08-04 07:40:06 +02:00
2025-08-04 08:31:45 +02:00
debugPrint ( " Lizenz " .. i .. " : " .. license.license_type .. " (Aktiv: " .. tostring ( license.is_active ) .. " ) " )
2025-08-04 07:40:06 +02:00
end
2025-08-04 08:31:45 +02:00
debugPrint ( " Sende " .. # licenses .. " Lizenzen an Client " )
TriggerClientEvent ( ' license-system:client:receivePlayerLicenses ' , src , licenses , targetId , targetName )
2025-08-04 07:40:06 +02:00
end )
end )
2025-08-04 06:14:47 +02:00
2025-08-04 08:31:45 +02:00
-- EVENT: Berechtigung prüfen
RegisterNetEvent ( ' license-system:server:checkPermission ' , function ( licenseType )
local src = source
debugPrint ( " === Event: checkPermission === " )
debugPrint ( " Source: " .. src .. " , LicenseType: " .. tostring ( licenseType ) )
2025-08-04 08:12:36 +02:00
2025-08-04 08:31:45 +02:00
local hasAuth = hasPermission ( src , licenseType )
2025-08-04 08:12:36 +02:00
debugPrint ( " Berechtigung für Lizenz " .. licenseType .. " : " .. tostring ( hasAuth ) )
2025-08-04 08:31:45 +02:00
TriggerClientEvent ( ' license-system:client:receivePermission ' , src , hasAuth , licenseType )
2025-08-04 07:40:06 +02:00
end )
2025-08-04 06:14:47 +02:00
2025-08-04 08:31:45 +02:00
-- EVENT: Lizenz ausstellen
2025-08-04 07:40:06 +02:00
RegisterNetEvent ( ' license-system:server:issueLicense ' , function ( targetId , licenseType , classes )
2025-08-04 06:14:47 +02:00
local src = source
2025-08-04 08:31:45 +02:00
debugPrint ( " === Event: issueLicense === " )
debugPrint ( " Von: " .. src .. " , Für: " .. targetId .. " , Typ: " .. licenseType )
2025-08-04 08:12:36 +02:00
2025-08-04 06:14:47 +02:00
local Player = QBCore.Functions . GetPlayer ( src )
2025-08-04 07:40:06 +02:00
local TargetPlayer = QBCore.Functions . GetPlayer ( targetId )
2025-08-04 06:14:47 +02:00
2025-08-04 07:40:06 +02:00
if not Player or not TargetPlayer then
TriggerClientEvent ( ' QBCore:Notify ' , src , Config.Notifications . no_players_nearby.message , Config.Notifications . no_players_nearby.type )
return
end
2025-08-04 06:14:47 +02:00
2025-08-04 07:40:06 +02:00
-- Berechtigung prüfen
if not hasPermission ( src , licenseType ) then
TriggerClientEvent ( ' QBCore:Notify ' , src , Config.Notifications . no_permission.message , Config.Notifications . no_permission.type )
2025-08-04 06:14:47 +02:00
return
end
2025-08-04 07:40:06 +02:00
-- Lizenz-Konfiguration prüfen
local licenseConfig = Config.LicenseTypes [ licenseType ]
if not licenseConfig then
TriggerClientEvent ( ' QBCore:Notify ' , src , ' Unbekannter Lizenztyp! ' , ' error ' )
return
end
-- Benötigte Items prüfen
if not hasRequiredItems ( targetId , licenseType ) then
TriggerClientEvent ( ' QBCore:Notify ' , src , Config.Notifications . missing_items.message , Config.Notifications . missing_items.type )
return
end
-- Geld prüfen (falls Kosten anfallen)
if licenseConfig.price > 0 then
if TargetPlayer.PlayerData . money.cash < licenseConfig.price then
TriggerClientEvent ( ' QBCore:Notify ' , src , Config.Notifications . insufficient_funds.message , Config.Notifications . insufficient_funds.type )
return
2025-08-04 06:14:47 +02:00
end
2025-08-04 07:40:06 +02:00
-- Geld abziehen
TargetPlayer.Functions . RemoveMoney ( ' cash ' , licenseConfig.price , ' license-fee ' )
2025-08-04 08:12:36 +02:00
debugPrint ( " Geld abgezogen: " .. licenseConfig.price .. " $ von " .. TargetPlayer.PlayerData . charinfo.firstname )
2025-08-04 07:40:06 +02:00
end
-- Alte Lizenz deaktivieren
2025-08-04 08:12:36 +02:00
MySQL.Async . execute ( ' UPDATE player_licenses SET is_active = 0 WHERE citizenid = ? AND license_type = ? ' , {
2025-08-04 07:40:06 +02:00
TargetPlayer.PlayerData . citizenid ,
licenseType
2025-08-04 08:12:36 +02:00
} , function ( affectedRows )
debugPrint ( " Alte Lizenzen deaktiviert: " .. affectedRows )
end )
2025-08-04 07:40:06 +02:00
-- Neue Lizenz erstellen
local success = createLicense ( TargetPlayer.PlayerData . citizenid , licenseType , Player.PlayerData . citizenid , classes )
if success then
TriggerClientEvent ( ' QBCore:Notify ' , src , Config.Notifications . license_granted.message , Config.Notifications . license_granted.type )
TriggerClientEvent ( ' QBCore:Notify ' , targetId , ' Du hast eine neue ' .. licenseConfig.label .. ' erhalten! ' , ' success ' )
2025-08-04 08:31:45 +02:00
-- Client über erfolgreiche Ausstellung informieren
TriggerClientEvent ( ' license-system:client:licenseIssued ' , src , targetId , licenseType )
2025-08-04 07:40:06 +02:00
-- Log erstellen
debugPrint ( Player.PlayerData . charinfo.firstname .. ' ' .. Player.PlayerData . charinfo.lastname .. ' hat ' .. TargetPlayer.PlayerData . charinfo.firstname .. ' ' .. TargetPlayer.PlayerData . charinfo.lastname .. ' eine ' .. licenseConfig.label .. ' ausgestellt ' )
else
TriggerClientEvent ( ' QBCore:Notify ' , src , ' Fehler beim Ausstellen der Lizenz! ' , ' error ' )
end
2025-08-04 06:14:47 +02:00
end )
2025-08-04 08:31:45 +02:00
-- EVENT: Lizenz entziehen
2025-08-04 07:40:06 +02:00
RegisterNetEvent ( ' license-system:server:revokeLicense ' , function ( targetId , licenseType )
2025-08-04 06:14:47 +02:00
local src = source
2025-08-04 08:31:45 +02:00
debugPrint ( " === Event: revokeLicense === " )
debugPrint ( " Von: " .. src .. " , Für: " .. targetId .. " , Typ: " .. licenseType )
2025-08-04 08:12:36 +02:00
2025-08-04 06:14:47 +02:00
local Player = QBCore.Functions . GetPlayer ( src )
2025-08-04 07:40:06 +02:00
local TargetPlayer = QBCore.Functions . GetPlayer ( targetId )
2025-08-04 06:14:47 +02:00
2025-08-04 07:40:06 +02:00
if not Player or not TargetPlayer then
TriggerClientEvent ( ' QBCore:Notify ' , src , Config.Notifications . no_players_nearby.message , Config.Notifications . no_players_nearby.type )
return
end
2025-08-04 06:14:47 +02:00
2025-08-04 07:40:06 +02:00
-- Berechtigung prüfen
if not hasPermission ( src , licenseType ) then
TriggerClientEvent ( ' QBCore:Notify ' , src , Config.Notifications . no_permission.message , Config.Notifications . no_permission.type )
2025-08-04 06:14:47 +02:00
return
end
2025-08-04 07:40:06 +02:00
-- Lizenz deaktivieren
2025-08-04 08:12:36 +02:00
MySQL.Async . execute ( ' UPDATE player_licenses SET is_active = 0 WHERE citizenid = ? AND license_type = ? AND is_active = 1 ' , {
2025-08-04 07:40:06 +02:00
TargetPlayer.PlayerData . citizenid ,
licenseType
} , function ( affectedRows )
if affectedRows > 0 then
TriggerClientEvent ( ' QBCore:Notify ' , src , Config.Notifications . license_revoked.message , Config.Notifications . license_revoked.type )
2025-08-04 08:12:36 +02:00
TriggerClientEvent ( ' QBCore:Notify ' , targetId , ' Deine ' .. ( Config.LicenseTypes [ licenseType ] and Config.LicenseTypes [ licenseType ] . label or licenseType ) .. ' wurde entzogen! ' , ' error ' )
2025-08-04 07:40:06 +02:00
2025-08-04 08:12:36 +02:00
-- Cache aktualisieren
if licenseCache [ TargetPlayer.PlayerData . citizenid ] then
licenseCache [ TargetPlayer.PlayerData . citizenid ] [ licenseType ] = nil
end
2025-08-04 08:31:45 +02:00
-- Client über erfolgreiche Entziehung informieren
TriggerClientEvent ( ' license-system:client:licenseRevoked ' , src , targetId , licenseType )
2025-08-04 08:12:36 +02:00
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 ' )
2025-08-04 07:40:06 +02:00
else
TriggerClientEvent ( ' QBCore:Notify ' , src , ' Keine aktive Lizenz gefunden! ' , ' error ' )
end
2025-08-04 06:14:47 +02:00
end )
end )
2025-08-04 08:31:45 +02:00
-- EVENT: Foto speichern
2025-08-04 07:40:06 +02:00
RegisterNetEvent ( ' license-system:server:savePhoto ' , function ( citizenid , photoData )
2025-08-04 06:14:47 +02:00
local src = source
2025-08-04 08:31:45 +02:00
debugPrint ( " === Event: savePhoto === " )
debugPrint ( " CitizenID: " .. citizenid )
2025-08-04 06:14:47 +02:00
2025-08-04 08:12:36 +02:00
local Player = QBCore.Functions . GetPlayer ( src )
2025-08-04 06:14:47 +02:00
if not Player then return end
2025-08-04 07:40:06 +02:00
-- Foto in der Datenbank speichern
2025-08-04 08:12:36 +02:00
MySQL.Async . execute ( ' UPDATE player_licenses SET photo_url = ? WHERE citizenid = ? AND is_active = 1 ' , {
2025-08-04 07:40:06 +02:00
photoData ,
citizenid
2025-08-04 06:14:47 +02:00
} , function ( affectedRows )
if affectedRows > 0 then
2025-08-04 07:40:06 +02:00
TriggerClientEvent ( ' QBCore:Notify ' , src , Config.Notifications . photo_saved.message , Config.Notifications . photo_saved.type )
debugPrint ( " Foto gespeichert für: " .. citizenid )
2025-08-04 06:14:47 +02:00
else
2025-08-04 07:40:06 +02:00
TriggerClientEvent ( ' QBCore:Notify ' , src , ' Fehler beim Speichern des Fotos! ' , ' error ' )
2025-08-04 06:14:47 +02:00
end
end )
end )
2025-08-04 07:40:06 +02:00
-- Admin-Kommandos
QBCore.Commands . Add ( ' givelicense ' , ' Lizenz an Spieler vergeben ' , {
{ name = ' id ' , help = ' Spieler ID ' } ,
{ name = ' type ' , help = ' Lizenztyp ' } ,
{ name = ' classes ' , help = ' Klassen (optional) ' }
} , true , function ( source , args )
local targetId = tonumber ( args [ 1 ] )
local licenseType = args [ 2 ]
local classes = args [ 3 ] and { args [ 3 ] } or nil
2025-08-04 08:12:36 +02:00
debugPrint ( " Admin-Command: givelicense - ID: " .. tostring ( targetId ) .. " , Typ: " .. tostring ( licenseType ) )
2025-08-04 07:40:06 +02:00
if not targetId or not licenseType then
TriggerClientEvent ( ' QBCore:Notify ' , source , ' Verwendung: /givelicense [id] [typ] [klassen] ' , ' error ' )
return
2025-08-04 06:14:47 +02:00
end
2025-08-04 07:40:06 +02:00
if not Config.LicenseTypes [ licenseType ] then
TriggerClientEvent ( ' QBCore:Notify ' , source , ' Unbekannter Lizenztyp! ' , ' error ' )
return
end
TriggerEvent ( ' license-system:server:issueLicense ' , targetId , licenseType , classes )
end , ' admin ' )
2025-08-04 06:14:47 +02:00
2025-08-04 07:40:06 +02:00
QBCore.Commands . Add ( ' revokelicense ' , ' Lizenz entziehen ' , {
{ name = ' id ' , help = ' Spieler ID ' } ,
{ name = ' type ' , help = ' Lizenztyp ' }
} , true , function ( source , args )
local targetId = tonumber ( args [ 1 ] )
local licenseType = args [ 2 ]
2025-08-04 08:12:36 +02:00
debugPrint ( " Admin-Command: revokelicense - ID: " .. tostring ( targetId ) .. " , Typ: " .. tostring ( licenseType ) )
2025-08-04 07:40:06 +02:00
if not targetId or not licenseType then
TriggerClientEvent ( ' QBCore:Notify ' , source , ' Verwendung: /revokelicense [id] [typ] ' , ' error ' )
return
end
TriggerEvent ( ' license-system:server:revokeLicense ' , targetId , licenseType )
end , ' admin ' )
2025-08-04 06:14:47 +02:00
2025-08-04 07:40:06 +02:00
-- Cleanup-Task für abgelaufene Lizenzen
if Config.Database . auto_cleanup then
CreateThread ( function ( )
while true do
Wait ( 24 * 60 * 60 * 1000 ) -- Einmal täglich
local cutoffDate = os.time ( ) - ( Config.Database . cleanup_days * 24 * 60 * 60 )
2025-08-04 08:12:36 +02:00
MySQL.Async . execute ( ' DELETE FROM player_licenses WHERE is_active = 0 AND created_at < ? ' , {
2025-08-04 07:40:06 +02:00
cutoffDate
} , function ( affectedRows )
if affectedRows > 0 then
debugPrint ( " Cleanup: " .. affectedRows .. " alte Lizenzen gelöscht " )
end
end )
end
end )
end
2025-08-04 06:14:47 +02:00
2025-08-04 07:40:06 +02:00
-- Lizenz-Ablauf-Checker
CreateThread ( function ( )
while true do
Wait ( 60 * 60 * 1000 ) -- Jede Stunde
2025-08-04 08:12:36 +02:00
MySQL.Async . fetchAll ( ' SELECT * FROM player_licenses WHERE is_active = 1 AND expire_date IS NOT NULL ' , { } , function ( result )
2025-08-04 07:40:06 +02:00
if result then
for _ , license in ipairs ( result ) do
2025-08-04 08:12:36 +02:00
if isLicenseExpired ( license.expire_date ) then
2025-08-04 07:40:06 +02:00
-- Lizenz als abgelaufen markieren
2025-08-04 08:12:36 +02:00
MySQL.Async . execute ( ' UPDATE player_licenses SET is_active = 0 WHERE id = ? ' , {
2025-08-04 07:40:06 +02:00
license.id
} )
debugPrint ( " Lizenz abgelaufen: " .. license.license_type .. " für " .. license.citizenid )
end
2025-08-04 06:14:47 +02:00
end
end
2025-08-04 07:40:06 +02:00
end )
2025-08-04 06:14:47 +02:00
end
end )
2025-08-04 06:51:25 +02:00
2025-08-04 07:40:06 +02:00
-- Resource Start/Stop Events
AddEventHandler ( ' onResourceStart ' , function ( resourceName )
if GetCurrentResourceName ( ) == resourceName then
2025-08-04 08:31:45 +02:00
debugPrint ( " License-System Server gestartet (Event-basiert) " )
2025-08-04 07:40:06 +02:00
-- Datenbank-Tabelle erstellen falls nicht vorhanden
MySQL.Async . execute ( [ [
CREATE TABLE IF NOT EXISTS player_licenses (
id INT AUTO_INCREMENT PRIMARY KEY ,
citizenid VARCHAR ( 50 ) NOT NULL ,
license_type VARCHAR ( 50 ) NOT NULL ,
issue_date VARCHAR ( 20 ) NOT NULL ,
expire_date VARCHAR ( 20 ) NULL ,
issued_by VARCHAR ( 50 ) NULL ,
2025-08-04 08:12:36 +02:00
is_active TINYINT ( 1 ) DEFAULT 1 ,
2025-08-04 07:40:06 +02:00
classes TEXT NULL ,
photo_url TEXT NULL ,
notes TEXT NULL ,
created_at BIGINT NOT NULL ,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ,
INDEX idx_citizenid ( citizenid ) ,
INDEX idx_license_type ( license_type ) ,
INDEX idx_active ( is_active )
)
2025-08-04 08:12:36 +02:00
] ] , { } , function ( success )
if success then
debugPrint ( " Datenbank-Tabelle erfolgreich erstellt/überprüft " )
else
debugPrint ( " ^1Fehler beim Erstellen der Datenbank-Tabelle!^7 " )
end
end )
2025-08-04 06:51:25 +02:00
end
end )
2025-08-04 07:40:06 +02:00
AddEventHandler ( ' onResourceStop ' , function ( resourceName )
if GetCurrentResourceName ( ) == resourceName then
debugPrint ( " License-System Server gestoppt " )
2025-08-04 08:12:36 +02:00
-- Cache leeren
licenseCache = { }
2025-08-04 07:40:06 +02:00
end
2025-08-04 06:51:25 +02:00
end )