Create main.lua
This commit is contained in:
		
							parent
							
								
									1a037cf4f1
								
							
						
					
					
						commit
						ecd6dddfde
					
				
					 1 changed files with 722 additions and 0 deletions
				
			
		
							
								
								
									
										722
									
								
								resources/[tools]/nordi_license/server/main.lua
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										722
									
								
								resources/[tools]/nordi_license/server/main.lua
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,722 @@
 | 
			
		|||
local QBCore = exports['qb-core']:GetCoreObject()
 | 
			
		||||
 | 
			
		||||
-- Lokale Variablen
 | 
			
		||||
local licenseCache = {}
 | 
			
		||||
local cacheTimeout = 300000 -- 5 Minuten
 | 
			
		||||
 | 
			
		||||
-- Hilfsfunktionen
 | 
			
		||||
local function debugPrint(message)
 | 
			
		||||
    if Config.Debug then
 | 
			
		||||
        print("^3[License-System Server] " .. message .. "^7")
 | 
			
		||||
    end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Spieler-Name abrufen
 | 
			
		||||
local function getPlayerName(src)
 | 
			
		||||
    local Player = QBCore.Functions.GetPlayer(src)
 | 
			
		||||
    if not Player then return "Unbekannt" end
 | 
			
		||||
    
 | 
			
		||||
    local charinfo = Player.PlayerData.charinfo
 | 
			
		||||
    if charinfo and charinfo.firstname and charinfo.lastname then
 | 
			
		||||
        return charinfo.firstname .. " " .. charinfo.lastname
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    return "Unbekannt"
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Spieler-Daten abrufen
 | 
			
		||||
local function getPlayerData(src)
 | 
			
		||||
    local Player = QBCore.Functions.GetPlayer(src)
 | 
			
		||||
    if not Player then return nil end
 | 
			
		||||
    
 | 
			
		||||
    return {
 | 
			
		||||
        citizenid = Player.PlayerData.citizenid,
 | 
			
		||||
        name = getPlayerName(src),
 | 
			
		||||
        charinfo = Player.PlayerData.charinfo,
 | 
			
		||||
        job = Player.PlayerData.job
 | 
			
		||||
    }
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Berechtigung prüfen
 | 
			
		||||
local function hasPermission(src)
 | 
			
		||||
    local Player = QBCore.Functions.GetPlayer(src)
 | 
			
		||||
    if not Player then return false end
 | 
			
		||||
    
 | 
			
		||||
    local job = Player.PlayerData.job
 | 
			
		||||
    if not job then return false end
 | 
			
		||||
    
 | 
			
		||||
    local hasAuth = Config.AuthorizedJobs[job.name] or false
 | 
			
		||||
    debugPrint("Berechtigung für " .. job.name .. ": " .. tostring(hasAuth))
 | 
			
		||||
    return hasAuth
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Cache-Funktionen
 | 
			
		||||
local function getCachedLicense(citizenid, licenseType)
 | 
			
		||||
    local cacheKey = citizenid .. "_" .. licenseType
 | 
			
		||||
    local cached = licenseCache[cacheKey]
 | 
			
		||||
    
 | 
			
		||||
    if cached and (os.time() * 1000 - cached.timestamp) < cacheTimeout then
 | 
			
		||||
        debugPrint("Cache-Hit für: " .. cacheKey)
 | 
			
		||||
        return cached.data
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    return nil
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function setCachedLicense(citizenid, licenseType, data)
 | 
			
		||||
    local cacheKey = citizenid .. "_" .. licenseType
 | 
			
		||||
    licenseCache[cacheKey] = {
 | 
			
		||||
        data = data,
 | 
			
		||||
        timestamp = os.time() * 1000
 | 
			
		||||
    }
 | 
			
		||||
    debugPrint("Lizenz gecacht: " .. cacheKey)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Cache bereinigen
 | 
			
		||||
local function cleanupCache()
 | 
			
		||||
    local now = os.time() * 1000
 | 
			
		||||
    local cleaned = 0
 | 
			
		||||
    
 | 
			
		||||
    for key, cached in pairs(licenseCache) do
 | 
			
		||||
        if (now - cached.timestamp) > cacheTimeout then
 | 
			
		||||
            licenseCache[key] = nil
 | 
			
		||||
            cleaned = cleaned + 1
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    if cleaned > 0 then
 | 
			
		||||
        debugPrint("Cache bereinigt: " .. cleaned .. " Einträge")
 | 
			
		||||
    end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Cache-Cleanup Thread
 | 
			
		||||
CreateThread(function()
 | 
			
		||||
    while true do
 | 
			
		||||
        Wait(300000) -- 5 Minuten
 | 
			
		||||
        cleanupCache()
 | 
			
		||||
    end
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
-- Spieler-Name aus JSON extrahieren (MariaDB-kompatibel)
 | 
			
		||||
local function extractPlayerName(charinfo_json)
 | 
			
		||||
    if not charinfo_json then return "Unbekannt" end
 | 
			
		||||
    
 | 
			
		||||
    local success, charinfo = pcall(json.decode, charinfo_json)
 | 
			
		||||
    if success and charinfo and charinfo.firstname and charinfo.lastname then
 | 
			
		||||
        return charinfo.firstname .. " " .. charinfo.lastname
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    return "Unbekannt"
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Lizenz aus Datenbank abrufen (KORRIGIERT für MariaDB)
 | 
			
		||||
local function getLicenseFromDB(citizenid, licenseType)
 | 
			
		||||
    debugPrint("=== getLicenseFromDB START ===")
 | 
			
		||||
    debugPrint("CitizenID: " .. tostring(citizenid))
 | 
			
		||||
    debugPrint("LicenseType: " .. tostring(licenseType))
 | 
			
		||||
    
 | 
			
		||||
    -- Cache prüfen
 | 
			
		||||
    local cached = getCachedLicense(citizenid, licenseType)
 | 
			
		||||
    if cached then
 | 
			
		||||
        return cached
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    -- MariaDB-kompatible Query ohne JSON-Operatoren
 | 
			
		||||
    local query = [[
 | 
			
		||||
        SELECT pl.*, 
 | 
			
		||||
               p.charinfo as holder_charinfo,
 | 
			
		||||
               pi.charinfo as issued_by_charinfo
 | 
			
		||||
        FROM player_licenses pl
 | 
			
		||||
        LEFT JOIN players p ON p.citizenid = pl.citizenid
 | 
			
		||||
        LEFT JOIN players pi ON pi.citizenid = pl.issued_by
 | 
			
		||||
        WHERE pl.citizenid = ? AND pl.license_type = ?
 | 
			
		||||
        ORDER BY pl.created_at DESC
 | 
			
		||||
        LIMIT 1
 | 
			
		||||
    ]]
 | 
			
		||||
    
 | 
			
		||||
    local result = MySQL.query.await(query, {citizenid, licenseType})
 | 
			
		||||
    
 | 
			
		||||
    if result and #result > 0 then
 | 
			
		||||
        local license = result[1]
 | 
			
		||||
        
 | 
			
		||||
        -- Namen aus JSON extrahieren
 | 
			
		||||
        license.holder_name = extractPlayerName(license.holder_charinfo)
 | 
			
		||||
        license.issued_by_name = extractPlayerName(license.issued_by_charinfo)
 | 
			
		||||
        
 | 
			
		||||
        -- Fallback für issued_by_name
 | 
			
		||||
        if license.issued_by_name == "Unbekannt" then
 | 
			
		||||
            license.issued_by_name = "System"
 | 
			
		||||
        end
 | 
			
		||||
        
 | 
			
		||||
        -- Classes parsen
 | 
			
		||||
        if license.classes then
 | 
			
		||||
            local success, classes = pcall(json.decode, license.classes)
 | 
			
		||||
            if success and type(classes) == "table" then
 | 
			
		||||
                license.classes = classes
 | 
			
		||||
            else
 | 
			
		||||
                license.classes = {}
 | 
			
		||||
            end
 | 
			
		||||
        else
 | 
			
		||||
            license.classes = {}
 | 
			
		||||
        end
 | 
			
		||||
        
 | 
			
		||||
        -- Cleanup - charinfo nicht mehr benötigt
 | 
			
		||||
        license.holder_charinfo = nil
 | 
			
		||||
        license.issued_by_charinfo = nil
 | 
			
		||||
        
 | 
			
		||||
        debugPrint("Lizenz aus DB geladen: " .. license.license_type)
 | 
			
		||||
        
 | 
			
		||||
        -- In Cache speichern
 | 
			
		||||
        setCachedLicense(citizenid, licenseType, license)
 | 
			
		||||
        
 | 
			
		||||
        return license
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    debugPrint("Keine Lizenz in DB gefunden")
 | 
			
		||||
    return nil
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Alle Lizenzen eines Spielers abrufen (KORRIGIERT für MariaDB)
 | 
			
		||||
local function getAllPlayerLicenses(citizenid)
 | 
			
		||||
    debugPrint("=== getAllPlayerLicenses START ===")
 | 
			
		||||
    debugPrint("CitizenID: " .. tostring(citizenid))
 | 
			
		||||
    
 | 
			
		||||
    -- MariaDB-kompatible Query
 | 
			
		||||
    local query = [[
 | 
			
		||||
        SELECT pl.*, 
 | 
			
		||||
               p.charinfo as holder_charinfo,
 | 
			
		||||
               pi.charinfo as issued_by_charinfo
 | 
			
		||||
        FROM player_licenses pl
 | 
			
		||||
        LEFT JOIN players p ON p.citizenid = pl.citizenid
 | 
			
		||||
        LEFT JOIN players pi ON pi.citizenid = pl.issued_by
 | 
			
		||||
        WHERE pl.citizenid = ?
 | 
			
		||||
        ORDER BY pl.license_type, pl.created_at DESC
 | 
			
		||||
    ]]
 | 
			
		||||
    
 | 
			
		||||
    local result = MySQL.query.await(query, {citizenid})
 | 
			
		||||
    
 | 
			
		||||
    if result and #result > 0 then
 | 
			
		||||
        local licenses = {}
 | 
			
		||||
        local seenTypes = {}
 | 
			
		||||
        
 | 
			
		||||
        for _, license in ipairs(result) do
 | 
			
		||||
            -- Nur die neueste Lizenz pro Typ nehmen
 | 
			
		||||
            if not seenTypes[license.license_type] then
 | 
			
		||||
                seenTypes[license.license_type] = true
 | 
			
		||||
                
 | 
			
		||||
                -- Namen aus JSON extrahieren
 | 
			
		||||
                license.holder_name = extractPlayerName(license.holder_charinfo)
 | 
			
		||||
                license.issued_by_name = extractPlayerName(license.issued_by_charinfo)
 | 
			
		||||
                
 | 
			
		||||
                -- Fallback für issued_by_name
 | 
			
		||||
                if license.issued_by_name == "Unbekannt" then
 | 
			
		||||
                    license.issued_by_name = "System"
 | 
			
		||||
                end
 | 
			
		||||
                
 | 
			
		||||
                -- Classes parsen
 | 
			
		||||
                if license.classes then
 | 
			
		||||
                    local success, classes = pcall(json.decode, license.classes)
 | 
			
		||||
                    if success and type(classes) == "table" then
 | 
			
		||||
                        license.classes = classes
 | 
			
		||||
                    else
 | 
			
		||||
                        license.classes = {}
 | 
			
		||||
                    end
 | 
			
		||||
                else
 | 
			
		||||
                    license.classes = {}
 | 
			
		||||
                end
 | 
			
		||||
                
 | 
			
		||||
                -- Cleanup
 | 
			
		||||
                license.holder_charinfo = nil
 | 
			
		||||
                license.issued_by_charinfo = nil
 | 
			
		||||
                
 | 
			
		||||
                table.insert(licenses, license)
 | 
			
		||||
            end
 | 
			
		||||
        end
 | 
			
		||||
        
 | 
			
		||||
        debugPrint("Gefundene Lizenzen: " .. #licenses)
 | 
			
		||||
        return licenses
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    debugPrint("Keine Lizenzen gefunden")
 | 
			
		||||
    return {}
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Lizenz in Datenbank speichern (KORRIGIERT)
 | 
			
		||||
local function saveLicenseToDB(citizenid, licenseType, issuedBy, classes)
 | 
			
		||||
    debugPrint("=== saveLicenseToDB START ===")
 | 
			
		||||
    debugPrint("CitizenID: " .. tostring(citizenid))
 | 
			
		||||
    debugPrint("LicenseType: " .. tostring(licenseType))
 | 
			
		||||
    debugPrint("IssuedBy: " .. tostring(issuedBy))
 | 
			
		||||
    
 | 
			
		||||
    local config = Config.LicenseTypes[licenseType]
 | 
			
		||||
    if not config then
 | 
			
		||||
        debugPrint("^1Fehler: Unbekannter Lizenztyp: " .. licenseType .. "^7")
 | 
			
		||||
        return false
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    -- Spieler-Name für das name-Feld abrufen (MariaDB-kompatibel)
 | 
			
		||||
    local holderQuery = "SELECT charinfo FROM players WHERE citizenid = ?"
 | 
			
		||||
    local holderResult = MySQL.query.await(holderQuery, {citizenid})
 | 
			
		||||
    local holderName = "Unbekannt"
 | 
			
		||||
    
 | 
			
		||||
    if holderResult and #holderResult > 0 and holderResult[1].charinfo then
 | 
			
		||||
        holderName = extractPlayerName(holderResult[1].charinfo)
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    -- Datum berechnen
 | 
			
		||||
    local issueDate = os.date("%d.%m.%Y")
 | 
			
		||||
    local expireDate = nil
 | 
			
		||||
    
 | 
			
		||||
    if config.validity_days then
 | 
			
		||||
        local expireTimestamp = os.time() + (config.validity_days * 24 * 60 * 60)
 | 
			
		||||
        expireDate = os.date("%d.%m.%Y", expireTimestamp)
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    -- Classes zu JSON konvertieren
 | 
			
		||||
    local classesJson = json.encode(classes or {})
 | 
			
		||||
    
 | 
			
		||||
    -- Alte Lizenz deaktivieren
 | 
			
		||||
    local deactivateQuery = "UPDATE player_licenses SET is_active = 0 WHERE citizenid = ? AND license_type = ?"
 | 
			
		||||
    MySQL.query.await(deactivateQuery, {citizenid, licenseType})
 | 
			
		||||
    
 | 
			
		||||
    -- Neue Lizenz einfügen
 | 
			
		||||
    local insertQuery = [[
 | 
			
		||||
        INSERT INTO player_licenses 
 | 
			
		||||
        (citizenid, license_type, name, issue_date, expire_date, issued_by, is_active, classes, created_at) 
 | 
			
		||||
        VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
 | 
			
		||||
    ]]
 | 
			
		||||
    
 | 
			
		||||
    local insertData = {
 | 
			
		||||
        citizenid,
 | 
			
		||||
        licenseType,
 | 
			
		||||
        holderName,
 | 
			
		||||
        issueDate,
 | 
			
		||||
        expireDate,
 | 
			
		||||
        issuedBy,
 | 
			
		||||
        1,
 | 
			
		||||
        classesJson,
 | 
			
		||||
        os.time()
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    debugPrint("Führe INSERT-Query aus...")
 | 
			
		||||
    debugPrint("Daten: " .. json.encode(insertData))
 | 
			
		||||
    
 | 
			
		||||
    local success, result = pcall(MySQL.insert.await, insertQuery, insertData)
 | 
			
		||||
    
 | 
			
		||||
    if success and result then
 | 
			
		||||
        debugPrint("Lizenz erfolgreich gespeichert. ID: " .. result)
 | 
			
		||||
        
 | 
			
		||||
        -- Cache invalidieren
 | 
			
		||||
        local cacheKey = citizenid .. "_" .. licenseType
 | 
			
		||||
        licenseCache[cacheKey] = nil
 | 
			
		||||
        
 | 
			
		||||
        return true
 | 
			
		||||
    else
 | 
			
		||||
        debugPrint("^1Fehler beim Speichern der Lizenz: " .. tostring(result) .. "^7")
 | 
			
		||||
        return false
 | 
			
		||||
    end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Lizenz entziehen
 | 
			
		||||
local function revokeLicenseInDB(citizenid, licenseType)
 | 
			
		||||
    debugPrint("=== revokeLicenseInDB START ===")
 | 
			
		||||
    debugPrint("CitizenID: " .. tostring(citizenid))
 | 
			
		||||
    debugPrint("LicenseType: " .. tostring(licenseType))
 | 
			
		||||
    
 | 
			
		||||
    local query = "UPDATE player_licenses SET is_active = 0 WHERE citizenid = ? AND license_type = ? AND is_active = 1"
 | 
			
		||||
    local success, result = pcall(MySQL.query.await, query, {citizenid, licenseType})
 | 
			
		||||
    
 | 
			
		||||
    if success and result then
 | 
			
		||||
        debugPrint("Lizenz erfolgreich entzogen")
 | 
			
		||||
        
 | 
			
		||||
        -- Cache invalidieren
 | 
			
		||||
        local cacheKey = citizenid .. "_" .. licenseType
 | 
			
		||||
        licenseCache[cacheKey] = nil
 | 
			
		||||
        
 | 
			
		||||
        return true
 | 
			
		||||
    else
 | 
			
		||||
        debugPrint("^1Fehler beim Entziehen der Lizenz: " .. tostring(result) .. "^7")
 | 
			
		||||
        return false
 | 
			
		||||
    end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Erweiterte Fehlerbehandlung für Datenbankoperationen
 | 
			
		||||
local function safeDBOperation(operation, errorMessage)
 | 
			
		||||
    local success, result = pcall(operation)
 | 
			
		||||
    if not success then
 | 
			
		||||
        debugPrint("^1DB-Fehler: " .. (errorMessage or "Unbekannt") .. "^7")
 | 
			
		||||
        debugPrint("^1Details: " .. tostring(result) .. "^7")
 | 
			
		||||
        return nil
 | 
			
		||||
    end
 | 
			
		||||
    return result
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- EVENT HANDLER: Lizenz anfordern
 | 
			
		||||
RegisterNetEvent('license-system:server:requestLicense', function(targetId)
 | 
			
		||||
    local src = source
 | 
			
		||||
    debugPrint("=== Event: requestLicense ===")
 | 
			
		||||
    debugPrint("Source: " .. src .. ", Target: " .. targetId)
 | 
			
		||||
    
 | 
			
		||||
    if not hasPermission(src) then
 | 
			
		||||
        debugPrint("Keine Berechtigung für Spieler: " .. src)
 | 
			
		||||
        TriggerClientEvent('license-system:client:receiveLicense', src, nil)
 | 
			
		||||
        return
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    local targetPlayer = QBCore.Functions.GetPlayer(targetId)
 | 
			
		||||
    if not targetPlayer then
 | 
			
		||||
        debugPrint("Ziel-Spieler nicht gefunden: " .. targetId)
 | 
			
		||||
        TriggerClientEvent('license-system:client:receiveLicense', src, nil)
 | 
			
		||||
        return
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    local citizenid = targetPlayer.PlayerData.citizenid
 | 
			
		||||
    
 | 
			
		||||
    -- Erste verfügbare Lizenz finden
 | 
			
		||||
    local foundLicense = nil
 | 
			
		||||
    for licenseType, _ in pairs(Config.LicenseTypes) do
 | 
			
		||||
        local license = safeDBOperation(function()
 | 
			
		||||
            return getLicenseFromDB(citizenid, licenseType)
 | 
			
		||||
        end, "Fehler beim Abrufen der Lizenz")
 | 
			
		||||
        
 | 
			
		||||
        if license and license.is_active == 1 then
 | 
			
		||||
            foundLicense = {
 | 
			
		||||
                license = license,
 | 
			
		||||
                config = Config.LicenseTypes[licenseType]
 | 
			
		||||
            }
 | 
			
		||||
            break
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    if foundLicense then
 | 
			
		||||
        debugPrint("Sende Lizenz an Client: " .. foundLicense.license.license_type)
 | 
			
		||||
        TriggerClientEvent('license-system:client:receiveLicense', src, foundLicense)
 | 
			
		||||
    else
 | 
			
		||||
        debugPrint("Keine aktive Lizenz gefunden")
 | 
			
		||||
        TriggerClientEvent('license-system:client:receiveLicense', src, nil)
 | 
			
		||||
    end
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
-- EVENT HANDLER: Eigene Lizenz anfordern
 | 
			
		||||
RegisterNetEvent('license-system:server:requestMyLicense', function(licenseType)
 | 
			
		||||
    local src = source
 | 
			
		||||
    debugPrint("=== Event: requestMyLicense ===")
 | 
			
		||||
    debugPrint("Source: " .. src .. ", LicenseType: " .. licenseType)
 | 
			
		||||
    
 | 
			
		||||
    local Player = QBCore.Functions.GetPlayer(src)
 | 
			
		||||
    if not Player then
 | 
			
		||||
        debugPrint("Spieler nicht gefunden: " .. src)
 | 
			
		||||
        TriggerClientEvent('license-system:client:receiveMyLicense', src, nil, licenseType)
 | 
			
		||||
        return
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    local citizenid = Player.PlayerData.citizenid
 | 
			
		||||
    local license = safeDBOperation(function()
 | 
			
		||||
        return getLicenseFromDB(citizenid, licenseType)
 | 
			
		||||
    end, "Fehler beim Abrufen der eigenen Lizenz")
 | 
			
		||||
    
 | 
			
		||||
    if license and license.is_active == 1 then
 | 
			
		||||
        local licenseData = {
 | 
			
		||||
            license = license,
 | 
			
		||||
            config = Config.LicenseTypes[licenseType]
 | 
			
		||||
        }
 | 
			
		||||
        debugPrint("Sende eigene Lizenz an Client: " .. licenseType)
 | 
			
		||||
        TriggerClientEvent('license-system:client:receiveMyLicense', src, licenseData, licenseType)
 | 
			
		||||
    else
 | 
			
		||||
        debugPrint("Keine aktive eigene Lizenz gefunden: " .. licenseType)
 | 
			
		||||
        TriggerClientEvent('license-system:client:receiveMyLicense', src, nil, licenseType)
 | 
			
		||||
    end
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
-- EVENT HANDLER: Alle Spieler-Lizenzen anfordern
 | 
			
		||||
RegisterNetEvent('license-system:server:requestPlayerLicenses', function(targetId)
 | 
			
		||||
    local src = source
 | 
			
		||||
    debugPrint("=== Event: requestPlayerLicenses ===")
 | 
			
		||||
    debugPrint("Source: " .. src .. ", Target: " .. targetId)
 | 
			
		||||
    
 | 
			
		||||
    if not hasPermission(src) then
 | 
			
		||||
        debugPrint("Keine Berechtigung für Spieler: " .. src)
 | 
			
		||||
        TriggerClientEvent('license-system:client:receivePlayerLicenses', src, {}, targetId, "Unbekannt")
 | 
			
		||||
        return
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    local targetPlayer = QBCore.Functions.GetPlayer(targetId)
 | 
			
		||||
    if not targetPlayer then
 | 
			
		||||
        debugPrint("Ziel-Spieler nicht gefunden: " .. targetId)
 | 
			
		||||
        TriggerClientEvent('license-system:client:receivePlayerLicenses', src, {}, targetId, "Unbekannt")
 | 
			
		||||
        return
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    local citizenid = targetPlayer.PlayerData.citizenid
 | 
			
		||||
    local targetName = getPlayerName(targetId)
 | 
			
		||||
    
 | 
			
		||||
    local licenses = safeDBOperation(function()
 | 
			
		||||
        return getAllPlayerLicenses(citizenid)
 | 
			
		||||
    end, "Fehler beim Abrufen aller Spieler-Lizenzen") or {}
 | 
			
		||||
    
 | 
			
		||||
    debugPrint("Sende " .. #licenses .. " Lizenzen für " .. targetName)
 | 
			
		||||
    TriggerClientEvent('license-system:client:receivePlayerLicenses', src, licenses, targetId, targetName)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
-- EVENT HANDLER: Lizenz ausstellen
 | 
			
		||||
RegisterNetEvent('license-system:server:issueLicense', function(targetId, licenseType, classes)
 | 
			
		||||
    local src = source
 | 
			
		||||
    debugPrint("=== Event: issueLicense ===")
 | 
			
		||||
    debugPrint("Source: " .. src .. ", Target: " .. targetId .. ", Type: " .. licenseType)
 | 
			
		||||
    
 | 
			
		||||
    if not hasPermission(src) then
 | 
			
		||||
        debugPrint("Keine Berechtigung für Spieler: " .. src)
 | 
			
		||||
        TriggerClientEvent('QBCore:Notify', src, Config.Notifications.no_permission.message, Config.Notifications.no_permission.type)
 | 
			
		||||
        return
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    local targetPlayer = QBCore.Functions.GetPlayer(targetId)
 | 
			
		||||
    if not targetPlayer then
 | 
			
		||||
        debugPrint("Ziel-Spieler nicht gefunden: " .. targetId)
 | 
			
		||||
        TriggerClientEvent('QBCore:Notify', src, 'Spieler nicht gefunden!', 'error')
 | 
			
		||||
        return
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    local issuerPlayer = QBCore.Functions.GetPlayer(src)
 | 
			
		||||
    if not issuerPlayer then
 | 
			
		||||
        debugPrint("Aussteller nicht gefunden: " .. src)
 | 
			
		||||
        return
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    local targetCitizenId = targetPlayer.PlayerData.citizenid
 | 
			
		||||
    local issuerCitizenId = issuerPlayer.PlayerData.citizenid
 | 
			
		||||
    
 | 
			
		||||
    -- Prüfen ob Lizenz bereits existiert
 | 
			
		||||
    local existingLicense = safeDBOperation(function()
 | 
			
		||||
        return getLicenseFromDB(targetCitizenId, licenseType)
 | 
			
		||||
    end, "Fehler beim Prüfen bestehender Lizenz")
 | 
			
		||||
    
 | 
			
		||||
    if existingLicense and existingLicense.is_active == 1 then
 | 
			
		||||
        debugPrint("Lizenz bereits vorhanden und aktiv")
 | 
			
		||||
        TriggerClientEvent('QBCore:Notify', src, 'Spieler hat bereits eine aktive ' .. (Config.LicenseTypes[licenseType].label or licenseType) .. '!', 'error')
 | 
			
		||||
        return
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    -- Kosten prüfen
 | 
			
		||||
    local config = Config.LicenseTypes[licenseType]
 | 
			
		||||
    if config.price and config.price > 0 then
 | 
			
		||||
        if issuerPlayer.PlayerData.money.cash < config.price then
 | 
			
		||||
            debugPrint("Nicht genug Geld für Lizenz-Ausstellung")
 | 
			
		||||
            TriggerClientEvent('QBCore:Notify', src, 'Nicht genug Bargeld! Benötigt: $' .. config.price, 'error')
 | 
			
		||||
            return
 | 
			
		||||
        end
 | 
			
		||||
        
 | 
			
		||||
        -- Geld abziehen
 | 
			
		||||
        issuerPlayer.Functions.RemoveMoney('cash', config.price, 'license-issued')
 | 
			
		||||
        TriggerClientEvent('QBCore:Notify', src, 'Lizenz-Gebühr bezahlt: $' .. config.price, 'success')
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    -- Lizenz in Datenbank speichern
 | 
			
		||||
    local success = safeDBOperation(function()
 | 
			
		||||
        return saveLicenseToDB(targetCitizenId, licenseType, issuerCitizenId, classes)
 | 
			
		||||
    end, "Fehler beim Speichern der Lizenz")
 | 
			
		||||
    
 | 
			
		||||
    if success then
 | 
			
		||||
        local targetName = getPlayerName(targetId)
 | 
			
		||||
        local issuerName = getPlayerName(src)
 | 
			
		||||
        
 | 
			
		||||
        debugPrint("Lizenz erfolgreich ausgestellt")
 | 
			
		||||
        
 | 
			
		||||
        -- Benachrichtigungen
 | 
			
		||||
        TriggerClientEvent('QBCore:Notify', src, 'Lizenz erfolgreich ausgestellt für ' .. targetName, 'success')
 | 
			
		||||
        TriggerClientEvent('QBCore:Notify', targetId, 'Du hast eine neue Lizenz erhalten: ' .. config.label, 'success')
 | 
			
		||||
        
 | 
			
		||||
        -- Events senden
 | 
			
		||||
        TriggerClientEvent('license-system:client:licenseIssued', src, targetId, licenseType)
 | 
			
		||||
        TriggerClientEvent('license-system:client:refreshMenu', src)
 | 
			
		||||
        
 | 
			
		||||
        -- Log
 | 
			
		||||
        debugPrint("Lizenz " .. licenseType .. " ausgestellt von " .. issuerName .. " für " .. targetName)
 | 
			
		||||
    else
 | 
			
		||||
        debugPrint("^1Fehler beim Ausstellen der Lizenz^7")
 | 
			
		||||
        TriggerClientEvent('QBCore:Notify', src, 'Fehler beim Ausstellen der Lizenz!', 'error')
 | 
			
		||||
    end
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
-- EVENT HANDLER: Lizenz entziehen
 | 
			
		||||
RegisterNetEvent('license-system:server:revokeLicense', function(targetId, licenseType)
 | 
			
		||||
    local src = source
 | 
			
		||||
    debugPrint("=== Event: revokeLicense ===")
 | 
			
		||||
    debugPrint("Source: " .. src .. ", Target: " .. targetId .. ", Type: " .. licenseType)
 | 
			
		||||
    
 | 
			
		||||
    if not hasPermission(src) then
 | 
			
		||||
        debugPrint("Keine Berechtigung für Spieler: " .. src)
 | 
			
		||||
        TriggerClientEvent('QBCore:Notify', src, Config.Notifications.no_permission.message, Config.Notifications.no_permission.type)
 | 
			
		||||
        return
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    local targetPlayer = QBCore.Functions.GetPlayer(targetId)
 | 
			
		||||
    if not targetPlayer then
 | 
			
		||||
        debugPrint("Ziel-Spieler nicht gefunden: " .. targetId)
 | 
			
		||||
        TriggerClientEvent('QBCore:Notify', src, 'Spieler nicht gefunden!', 'error')
 | 
			
		||||
        return
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    local targetCitizenId = targetPlayer.PlayerData.citizenid
 | 
			
		||||
    
 | 
			
		||||
    -- Lizenz entziehen
 | 
			
		||||
    local success = safeDBOperation(function()
 | 
			
		||||
        return revokeLicenseInDB(targetCitizenId, licenseType)
 | 
			
		||||
    end, "Fehler beim Entziehen der Lizenz")
 | 
			
		||||
    
 | 
			
		||||
    if success then
 | 
			
		||||
        local targetName = getPlayerName(targetId)
 | 
			
		||||
        local issuerName = getPlayerName(src)
 | 
			
		||||
        local config = Config.LicenseTypes[licenseType]
 | 
			
		||||
        
 | 
			
		||||
        debugPrint("Lizenz erfolgreich entzogen")
 | 
			
		||||
        
 | 
			
		||||
        -- Benachrichtigungen
 | 
			
		||||
        TriggerClientEvent('QBCore:Notify', src, 'Lizenz erfolgreich entzogen von ' .. targetName, 'success')
 | 
			
		||||
        TriggerClientEvent('QBCore:Notify', targetId, 'Deine Lizenz wurde entzogen: ' .. (config.label or licenseType), 'error')
 | 
			
		||||
        
 | 
			
		||||
        -- Events senden
 | 
			
		||||
        TriggerClientEvent('license-system:client:licenseRevoked', src, targetId, licenseType)
 | 
			
		||||
        TriggerClientEvent('license-system:client:refreshMenu', src)
 | 
			
		||||
        
 | 
			
		||||
        -- Log
 | 
			
		||||
        debugPrint("Lizenz " .. licenseType .. " entzogen von " .. issuerName .. " für " .. targetName)
 | 
			
		||||
    else
 | 
			
		||||
        debugPrint("^1Fehler beim Entziehen der Lizenz^7")
 | 
			
		||||
        TriggerClientEvent('QBCore:Notify', src, 'Fehler beim Entziehen der Lizenz!', 'error')
 | 
			
		||||
    end
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
-- EVENT HANDLER: Foto speichern
 | 
			
		||||
RegisterNetEvent('license-system:server:savePhoto', function(citizenid, photoData)
 | 
			
		||||
    local src = source
 | 
			
		||||
    debugPrint("=== Event: savePhoto ===")
 | 
			
		||||
    debugPrint("Source: " .. src .. ", CitizenID: " .. citizenid)
 | 
			
		||||
    
 | 
			
		||||
    -- Hier könnte das Foto in der Datenbank oder im Dateisystem gespeichert werden
 | 
			
		||||
    debugPrint("Foto-Daten erhalten für: " .. citizenid)
 | 
			
		||||
    
 | 
			
		||||
    TriggerClientEvent('QBCore:Notify', src, 'Foto gespeichert!', 'success')
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
-- EXPORT FUNKTIONEN
 | 
			
		||||
exports('hasLicense', function(citizenid, licenseType)
 | 
			
		||||
    if not citizenid or not licenseType then return false end
 | 
			
		||||
    
 | 
			
		||||
    local license = safeDBOperation(function()
 | 
			
		||||
        return getLicenseFromDB(citizenid, licenseType)
 | 
			
		||||
    end, "Fehler beim Prüfen der Lizenz")
 | 
			
		||||
    
 | 
			
		||||
    return license and license.is_active == 1
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
exports('issueLicense', function(citizenid, licenseType, issuedBy, classes)
 | 
			
		||||
    if not citizenid or not licenseType then return false end
 | 
			
		||||
    
 | 
			
		||||
    issuedBy = issuedBy or 'system'
 | 
			
		||||
    return safeDBOperation(function()
 | 
			
		||||
        return saveLicenseToDB(citizenid, licenseType, issuedBy, classes)
 | 
			
		||||
    end, "Fehler beim Ausstellen der Lizenz") or false
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
exports('revokeLicense', function(citizenid, licenseType)
 | 
			
		||||
    if not citizenid or not licenseType then return false end
 | 
			
		||||
    
 | 
			
		||||
    return safeDBOperation(function()
 | 
			
		||||
        return revokeLicenseInDB(citizenid, licenseType)
 | 
			
		||||
    end, "Fehler beim Entziehen der Lizenz") or false
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
exports('getPlayerLicenses', function(citizenid)
 | 
			
		||||
    if not citizenid then return {} end
 | 
			
		||||
    
 | 
			
		||||
    return safeDBOperation(function()
 | 
			
		||||
        return getAllPlayerLicenses(citizenid)
 | 
			
		||||
    end, "Fehler beim Abrufen der Spieler-Lizenzen") or {}
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
exports('getPlayerLicense', function(citizenid, licenseType)
 | 
			
		||||
    if not citizenid or not licenseType then return nil end
 | 
			
		||||
    
 | 
			
		||||
    return safeDBOperation(function()
 | 
			
		||||
        return getLicenseFromDB(citizenid, licenseType)
 | 
			
		||||
    end, "Fehler beim Abrufen der Lizenz")
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
-- INITIALISIERUNG
 | 
			
		||||
CreateThread(function()
 | 
			
		||||
    debugPrint("License-System Server gestartet (MariaDB-kompatibel)")
 | 
			
		||||
    
 | 
			
		||||
    -- Warten bis QBCore geladen ist
 | 
			
		||||
    while not QBCore do
 | 
			
		||||
        Wait(100)
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    debugPrint("QBCore erfolgreich geladen")
 | 
			
		||||
    
 | 
			
		||||
    -- Datenbank-Verbindung testen
 | 
			
		||||
    local testResult = safeDBOperation(function()
 | 
			
		||||
        return MySQL.query.await("SELECT 1 as test")
 | 
			
		||||
    end, "Datenbank-Verbindungstest")
 | 
			
		||||
    
 | 
			
		||||
    if testResult then
 | 
			
		||||
        debugPrint("Datenbank-Verbindung erfolgreich")
 | 
			
		||||
    else
 | 
			
		||||
        debugPrint("^1Datenbank-Verbindung fehlgeschlagen^7")
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    debugPrint("License-System Server vollständig initialisiert")
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
-- CLEANUP
 | 
			
		||||
AddEventHandler('onResourceStop', function(resourceName)
 | 
			
		||||
    if GetCurrentResourceName() == resourceName then
 | 
			
		||||
        debugPrint("License-System Server gestoppt")
 | 
			
		||||
        licenseCache = {}
 | 
			
		||||
    end
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
-- DEBUG COMMANDS
 | 
			
		||||
RegisterCommand('licensestats', function(source, args, rawCommand)
 | 
			
		||||
    if source == 0 then -- Console only
 | 
			
		||||
        local cacheCount = 0
 | 
			
		||||
        for _ in pairs(licenseCache) do
 | 
			
		||||
            cacheCount = cacheCount + 1
 | 
			
		||||
        end
 | 
			
		||||
        
 | 
			
		||||
        print("=== LICENSE SYSTEM STATS ===")
 | 
			
		||||
        print("Cache Entries: " .. cacheCount)
 | 
			
		||||
        print("Config License Types: " .. (Config.LicenseTypes and #Config.LicenseTypes or 0))
 | 
			
		||||
        print("============================")
 | 
			
		||||
    end
 | 
			
		||||
end, true)
 | 
			
		||||
 | 
			
		||||
RegisterCommand('licenseclearcache', function(source, args, rawCommand)
 | 
			
		||||
    if source == 0 then -- Console only
 | 
			
		||||
        local oldCount = 0
 | 
			
		||||
        for _ in pairs(licenseCache) do
 | 
			
		||||
            oldCount = oldCount + 1
 | 
			
		||||
        end
 | 
			
		||||
        
 | 
			
		||||
        licenseCache = {}
 | 
			
		||||
        print("License-Cache geleert. Entfernte Einträge: " .. oldCount)
 | 
			
		||||
    end
 | 
			
		||||
end, true)
 | 
			
		||||
 | 
			
		||||
-- Erweiterte Logging-Funktion
 | 
			
		||||
local function logLicenseAction(action, src, targetId, licenseType, details)
 | 
			
		||||
    local timestamp = os.date("%Y-%m-%d %H:%M:%S")
 | 
			
		||||
    local srcName = getPlayerName(src)
 | 
			
		||||
    local targetName = targetId and getPlayerName(targetId) or "N/A"
 | 
			
		||||
    
 | 
			
		||||
    local logMessage = string.format(
 | 
			
		||||
        "[%s] %s | Quelle: %s (%s) | Ziel: %s (%s) | Typ: %s | Details: %s",
 | 
			
		||||
        timestamp, action, srcName, src, targetName, targetId or "N/A", licenseType or "N/A", details or "N/A"
 | 
			
		||||
    )
 | 
			
		||||
    
 | 
			
		||||
    debugPrint("LOG: " .. logMessage)
 | 
			
		||||
    
 | 
			
		||||
    -- Hier könnte das Log in eine Datei oder Datenbank geschrieben werden
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
debugPrint("License-System Server vollständig geladen (MariaDB-kompatibel)")
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue