1
0
Fork 0
forked from Simnation/Main

Update main.lua

This commit is contained in:
Nordi98 2025-08-04 09:15:25 +02:00
parent e4f7b961d5
commit 9461b582f6

View file

@ -35,7 +35,7 @@ local function hasPermission(src)
return Config.AuthorizedJobs[job.name] or false
end
-- Cache-Funktionen
-- Cache-Funktionen (KORRIGIERT - Aggressive Cache-Invalidierung)
local function getCachedLicense(citizenid, licenseType)
local cacheKey = citizenid .. "_" .. licenseType
local cached = licenseCache[cacheKey]
@ -57,6 +57,24 @@ local function setCachedLicense(citizenid, licenseType, data)
debugPrint("Lizenz gecacht: " .. cacheKey)
end
-- Cache invalidieren (ERWEITERT)
local function invalidateCache(citizenid, licenseType)
if licenseType then
-- Spezifische Lizenz invalidieren
local cacheKey = citizenid .. "_" .. licenseType
licenseCache[cacheKey] = nil
debugPrint("Cache invalidiert für: " .. cacheKey)
else
-- Alle Lizenzen des Spielers invalidieren
for key, _ in pairs(licenseCache) do
if string.find(key, citizenid .. "_") then
licenseCache[key] = nil
debugPrint("Cache invalidiert für: " .. key)
end
end
end
end
-- Spieler-Name aus JSON extrahieren
local function extractPlayerName(charinfo_json)
if not charinfo_json then return "Unbekannt" end
@ -94,61 +112,87 @@ local function safeDBOperation(operation, errorMessage, maxRetries)
return nil
end
-- KORRIGIERTE Lizenz-Abfrage (Erweiterte Suche)
local function getLicenseFromDB(citizenid, licenseType)
debugPrint("=== getLicenseFromDB START ===")
debugPrint("CitizenID: " .. tostring(citizenid))
debugPrint("LicenseType: " .. tostring(licenseType))
-- Lizenz-Status prüfen (NEUE FUNKTION)
local function isLicenseActive(license)
if not license then return false end
-- Cache prüfen
local cached = getCachedLicense(citizenid, licenseType)
if cached then
debugPrint("Lizenz aus Cache geladen")
return cached
-- is_active prüfen (1 = aktiv, 0 = inaktiv, nil = aktiv per default)
local isActive = license.is_active
if isActive == nil then
isActive = 1 -- Default: aktiv
end
-- ERWEITERTE SUCHE: Erst aktive, dann alle Lizenzen
local queries = {
-- 1. Suche nach aktiven Lizenzen (is_active = 1)
{
query = "SELECT * FROM player_licenses WHERE citizenid = ? AND license_type = ? AND is_active = 1 ORDER BY created_at DESC LIMIT 1",
description = "Aktive Lizenz"
},
-- 2. Suche nach allen Lizenzen (falls is_active nicht gesetzt)
{
query = "SELECT * FROM player_licenses WHERE citizenid = ? AND license_type = ? ORDER BY created_at DESC LIMIT 1",
description = "Neueste Lizenz"
},
-- 3. Fallback: Suche ohne is_active Bedingung
{
query = "SELECT * FROM player_licenses WHERE citizenid = ? AND license_type = ? ORDER BY id DESC LIMIT 1",
description = "Fallback-Suche"
}
}
if isActive ~= 1 then
debugPrint("Lizenz inaktiv (is_active = " .. tostring(isActive) .. ")")
return false
end
local license = nil
-- Ablaufdatum prüfen (falls vorhanden)
if license.expire_date and license.expire_date ~= "" then
local expireDate = license.expire_date
local currentDate = os.date("%d.%m.%Y")
for i, queryData in ipairs(queries) do
debugPrint("Versuche Query " .. i .. ": " .. queryData.description)
-- Einfache Datumsvergleich (DD.MM.YYYY)
local function parseDate(dateStr)
local day, month, year = dateStr:match("(%d+)%.(%d+)%.(%d+)")
if day and month and year then
return os.time({year = tonumber(year), month = tonumber(month), day = tonumber(day)})
end
return nil
end
local result = safeDBOperation(function()
return MySQL.query.await(queryData.query, {citizenid, licenseType})
end, "Fehler bei " .. queryData.description)
local expireTimestamp = parseDate(expireDate)
local currentTimestamp = parseDate(currentDate)
if result and #result > 0 then
license = result[1]
debugPrint("Lizenz gefunden mit Query " .. i .. ": " .. queryData.description)
break
else
debugPrint("Keine Lizenz mit Query " .. i .. " gefunden")
if expireTimestamp and currentTimestamp and expireTimestamp < currentTimestamp then
debugPrint("Lizenz abgelaufen: " .. expireDate .. " < " .. currentDate)
return false
end
end
if not license then
debugPrint("Lizenz ist aktiv und gültig")
return true
end
-- KORRIGIERTE Lizenz-Abfrage (Ohne Cache für frische Daten)
local function getLicenseFromDB(citizenid, licenseType, skipCache)
debugPrint("=== getLicenseFromDB START ===")
debugPrint("CitizenID: " .. tostring(citizenid))
debugPrint("LicenseType: " .. tostring(licenseType))
debugPrint("SkipCache: " .. tostring(skipCache))
-- Cache prüfen (nur wenn nicht übersprungen)
if not skipCache then
local cached = getCachedLicense(citizenid, licenseType)
if cached then
debugPrint("Lizenz aus Cache geladen")
return cached
end
end
-- Direkte DB-Abfrage (VEREINFACHT - nur aktive Lizenzen)
local query = [[
SELECT * FROM player_licenses
WHERE citizenid = ? AND license_type = ?
ORDER BY created_at DESC
LIMIT 1
]]
local result = safeDBOperation(function()
return MySQL.query.await(query, {citizenid, licenseType})
end, "Fehler beim Abrufen der Lizenz")
if not result or #result == 0 then
debugPrint("^1Keine Lizenz in DB gefunden für " .. citizenid .. " / " .. licenseType .. "^7")
return nil
end
local license = result[1]
debugPrint("Rohe Lizenz-Daten aus DB:")
debugPrint("ID: " .. tostring(license.id))
debugPrint("is_active: " .. tostring(license.is_active))
debugPrint("created_at: " .. tostring(license.created_at))
-- Spieler-Namen abrufen
local holderQuery = "SELECT charinfo FROM players WHERE citizenid = ?"
local holderResult = safeDBOperation(function()
@ -189,15 +233,27 @@ local function getLicenseFromDB(citizenid, licenseType)
license.classes = {}
end
-- is_active standardisieren (falls nicht gesetzt)
-- is_active normalisieren (WICHTIG!)
if license.is_active == nil then
license.is_active = 1
debugPrint("is_active war nil, auf 1 gesetzt")
end
-- Status prüfen
local isActive = isLicenseActive(license)
debugPrint("Lizenz-Status-Prüfung: " .. tostring(isActive))
if not isActive then
debugPrint("Lizenz ist nicht aktiv/gültig")
return nil
end
debugPrint("Lizenz erfolgreich geladen: " .. license.license_type .. " (Active: " .. tostring(license.is_active) .. ")")
-- In Cache speichern
setCachedLicense(citizenid, licenseType, license)
-- In Cache speichern (nur wenn aktiv)
if not skipCache then
setCachedLicense(citizenid, licenseType, license)
end
return license
end
@ -207,28 +263,12 @@ local function getAllPlayerLicenses(citizenid)
debugPrint("=== getAllPlayerLicenses START ===")
debugPrint("CitizenID: " .. tostring(citizenid))
-- Erweiterte Suche für alle Lizenzen
local queries = {
-- 1. Aktive Lizenzen
"SELECT * FROM player_licenses WHERE citizenid = ? AND is_active = 1 ORDER BY license_type, created_at DESC",
-- 2. Alle Lizenzen (Fallback)
"SELECT * FROM player_licenses WHERE citizenid = ? ORDER BY license_type, created_at DESC"
}
-- Alle Lizenzen abrufen (ohne is_active Filter)
local query = "SELECT * FROM player_licenses WHERE citizenid = ? ORDER BY license_type, created_at DESC"
local result = nil
for i, query in ipairs(queries) do
debugPrint("Versuche Abfrage " .. i .. " für alle Lizenzen")
result = safeDBOperation(function()
return MySQL.query.await(query, {citizenid})
end, "Fehler bei Abfrage " .. i)
if result and #result > 0 then
debugPrint("Lizenzen gefunden mit Abfrage " .. i .. ": " .. #result .. " Einträge")
break
end
end
local result = safeDBOperation(function()
return MySQL.query.await(query, {citizenid})
end, "Fehler beim Abrufen aller Lizenzen")
if not result or #result == 0 then
debugPrint("Keine Lizenzen gefunden für: " .. citizenid)
@ -284,20 +324,26 @@ local function getAllPlayerLicenses(citizenid)
license.classes = {}
end
-- is_active standardisieren
-- is_active normalisieren
if license.is_active == nil then
license.is_active = 1
end
table.insert(licenses, license)
-- Status prüfen und nur aktive Lizenzen hinzufügen
if isLicenseActive(license) then
table.insert(licenses, license)
debugPrint("Aktive Lizenz hinzugefügt: " .. license.license_type)
else
debugPrint("Inaktive Lizenz übersprungen: " .. license.license_type)
end
end
end
debugPrint("Verarbeitete Lizenzen: " .. #licenses)
debugPrint("Verarbeitete aktive Lizenzen: " .. #licenses)
return licenses
end
-- Lizenz in Datenbank speichern (KORRIGIERT)
-- Lizenz in Datenbank speichern (KORRIGIERT - Explizite is_active Setzung)
local function saveLicenseToDB(citizenid, licenseType, issuedBy, classes)
debugPrint("=== saveLicenseToDB START ===")
debugPrint("CitizenID: " .. tostring(citizenid))
@ -310,6 +356,9 @@ local function saveLicenseToDB(citizenid, licenseType, issuedBy, classes)
return false
end
-- Cache für diesen Spieler komplett invalidieren
invalidateCache(citizenid)
-- Spieler-Name abrufen
local holderQuery = "SELECT charinfo FROM players WHERE citizenid = ?"
local holderResult = safeDBOperation(function()
@ -333,17 +382,19 @@ local function saveLicenseToDB(citizenid, licenseType, issuedBy, classes)
-- Classes zu JSON konvertieren
local classesJson = json.encode(classes or {})
-- Alte Lizenz deaktivieren
-- WICHTIG: Alte Lizenz explizit deaktivieren
local deactivateQuery = "UPDATE player_licenses SET is_active = 0 WHERE citizenid = ? AND license_type = ?"
safeDBOperation(function()
local deactivateResult = safeDBOperation(function()
return MySQL.query.await(deactivateQuery, {citizenid, licenseType})
end, "Fehler beim Deaktivieren alter Lizenz")
-- Neue Lizenz einfügen
debugPrint("Alte Lizenzen deaktiviert: " .. tostring(deactivateResult ~= nil))
-- Neue Lizenz einfügen (EXPLIZIT is_active = 1)
local insertQuery = [[
INSERT INTO player_licenses
(citizenid, license_type, name, issue_date, expire_date, issued_by, is_active, classes, created_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
VALUES (?, ?, ?, ?, ?, ?, 1, ?, ?)
]]
local createdAt = os.time() -- Unix Timestamp
@ -355,7 +406,7 @@ local function saveLicenseToDB(citizenid, licenseType, issuedBy, classes)
issueDate,
expireDate,
issuedBy,
1, -- is_active = 1
-- is_active = 1 ist direkt in der Query
classesJson,
createdAt
}
@ -370,9 +421,18 @@ local function saveLicenseToDB(citizenid, licenseType, issuedBy, classes)
if result then
debugPrint("Lizenz erfolgreich gespeichert. ID: " .. result)
-- Cache invalidieren
local cacheKey = citizenid .. "_" .. licenseType
licenseCache[cacheKey] = nil
-- Cache komplett invalidieren (sicherstellen dass neue Daten geladen werden)
invalidateCache(citizenid)
-- Sofort neue Lizenz aus DB laden um zu verifizieren
Wait(100) -- Kurz warten
local newLicense = getLicenseFromDB(citizenid, licenseType, true) -- Skip Cache
if newLicense then
debugPrint("Neue Lizenz erfolgreich verifiziert: is_active = " .. tostring(newLicense.is_active))
else
debugPrint("^3Warnung: Neue Lizenz konnte nicht verifiziert werden^7")
end
return true
else
@ -381,13 +441,13 @@ local function saveLicenseToDB(citizenid, licenseType, issuedBy, classes)
end
end
-- Lizenz entziehen
-- Lizenz entziehen (KORRIGIERT)
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 = ?"
local query = "UPDATE player_licenses SET is_active = 0 WHERE citizenid = ? AND license_type = ? AND is_active = 1"
local result = safeDBOperation(function()
return MySQL.query.await(query, {citizenid, licenseType})
@ -397,8 +457,7 @@ local function revokeLicenseInDB(citizenid, licenseType)
debugPrint("Lizenz erfolgreich entzogen")
-- Cache invalidieren
local cacheKey = citizenid .. "_" .. licenseType
licenseCache[cacheKey] = nil
invalidateCache(citizenid, licenseType)
return true
else
@ -432,7 +491,7 @@ CreateThread(function()
end
end)
-- EVENT HANDLER: Lizenz anfordern (KORRIGIERT für Ausweis-Anzeige)
-- EVENT HANDLER: Lizenz anfordern
RegisterNetEvent('license-system:server:requestLicense', function(targetId)
local src = source
debugPrint("=== Event: requestLicense ===")
@ -459,7 +518,7 @@ RegisterNetEvent('license-system:server:requestLicense', function(targetId)
for _, licenseType in ipairs(licenseTypes) do
if Config.LicenseTypes[licenseType] then
local license = getLicenseFromDB(citizenid, licenseType)
local license = getLicenseFromDB(citizenid, licenseType, true) -- Skip Cache für frische Daten
if license then
foundLicense = {
@ -502,7 +561,7 @@ RegisterNetEvent('license-system:server:requestMyLicense', function(licenseType)
debugPrint("Kein Lizenztyp angegeben, verwende: " .. licenseType)
end
local license = getLicenseFromDB(citizenid, licenseType)
local license = getLicenseFromDB(citizenid, licenseType, true) -- Skip Cache für frische Daten
if license then
local licenseData = {
@ -544,7 +603,7 @@ RegisterNetEvent('license-system:server:requestPlayerLicenses', function(targetI
TriggerClientEvent('license-system:client:receivePlayerLicenses', src, licenses, targetId, targetName)
end)
-- EVENT HANDLER: Lizenz ausstellen
-- EVENT HANDLER: Lizenz ausstellen (KORRIGIERT)
RegisterNetEvent('license-system:server:issueLicense', function(targetId, licenseType, classes)
local src = source
debugPrint("=== Event: issueLicense ===")
@ -572,10 +631,10 @@ RegisterNetEvent('license-system:server:issueLicense', function(targetId, licens
local targetCitizenId = targetPlayer.PlayerData.citizenid
local issuerCitizenId = issuerPlayer.PlayerData.citizenid
-- Prüfen ob aktive Lizenz bereits existiert
local existingLicense = getLicenseFromDB(targetCitizenId, licenseType)
-- Prüfen ob aktive Lizenz bereits existiert (Skip Cache)
local existingLicense = getLicenseFromDB(targetCitizenId, licenseType, true)
if existingLicense and existingLicense.is_active == 1 then
if existingLicense then
debugPrint("Lizenz bereits vorhanden und aktiv")
TriggerClientEvent('QBCore:Notify', src, 'Spieler hat bereits eine aktive ' .. (Config.LicenseTypes[licenseType].label or licenseType) .. '!', 'error')
return
@ -663,7 +722,8 @@ RegisterNetEvent('license-system:server:revokeLicense', function(targetId, licen
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')
TriggerClientEvent('QBCore:Notify', src, 'Fehler beim Entziehen der Lizenz!',
'error')
end
end)
@ -671,8 +731,8 @@ end)
exports('hasLicense', function(citizenid, licenseType)
if not citizenid or not licenseType then return false end
local license = getLicenseFromDB(citizenid, licenseType)
return license ~= nil and (license.is_active == 1 or license.is_active == nil)
local license = getLicenseFromDB(citizenid, licenseType, true) -- Skip Cache für aktuelle Daten
return license ~= nil
end)
exports('issueLicense', function(citizenid, licenseType, issuedBy, classes)
@ -697,7 +757,7 @@ end)
exports('getPlayerLicense', function(citizenid, licenseType)
if not citizenid or not licenseType then return nil end
return getLicenseFromDB(citizenid, licenseType)
return getLicenseFromDB(citizenid, licenseType, true) -- Skip Cache
end)
-- DEBUG COMMAND: Lizenz manuell erstellen
@ -726,7 +786,7 @@ RegisterCommand('createlicense', function(source, args, rawCommand)
end
end, true)
-- DEBUG COMMAND: Lizenz prüfen
-- DEBUG COMMAND: Lizenz prüfen (ERWEITERT)
RegisterCommand('checklicense', function(source, args, rawCommand)
if source == 0 then -- Console only
if #args < 2 then
@ -737,30 +797,127 @@ RegisterCommand('checklicense', function(source, args, rawCommand)
local citizenid = args[1]
local licenseType = args[2]
local license = getLicenseFromDB(citizenid, licenseType)
-- Direkte DB-Abfrage ohne Cache
local query = "SELECT * FROM player_licenses WHERE citizenid = ? AND license_type = ? ORDER BY created_at DESC"
local result = MySQL.query.await(query, {citizenid, licenseType})
if license then
print("=== LIZENZ GEFUNDEN ===")
print("ID: " .. (license.id or "N/A"))
print("CitizenID: " .. (license.citizenid or "N/A"))
print("Typ: " .. (license.license_type or "N/A"))
print("Name: " .. (license.name or "N/A"))
print("Ausstellungsdatum: " .. (license.issue_date or "N/A"))
print("Ablaufdatum: " .. (license.expire_date or "N/A"))
print("Ausgestellt von: " .. (license.issued_by or "N/A"))
print("Aktiv: " .. tostring(license.is_active))
print("Klassen: " .. (license.classes and json.encode(license.classes) or "[]"))
print("Erstellt am: " .. (license.created_at or "N/A"))
print("=====================")
if result and #result > 0 then
print("=== ALLE LIZENZEN GEFUNDEN ===")
for i, license in ipairs(result) do
print("--- Lizenz " .. i .. " ---")
print("ID: " .. (license.id or "N/A"))
print("CitizenID: " .. (license.citizenid or "N/A"))
print("Typ: " .. (license.license_type or "N/A"))
print("Name: " .. (license.name or "N/A"))
print("Ausstellungsdatum: " .. (license.issue_date or "N/A"))
print("Ablaufdatum: " .. (license.expire_date or "N/A"))
print("Ausgestellt von: " .. (license.issued_by or "N/A"))
print("Aktiv (DB): " .. tostring(license.is_active))
print("Klassen: " .. (license.classes or "[]"))
print("Erstellt am: " .. (license.created_at or "N/A"))
print("---")
end
print("===============================")
-- Zusätzlich: Lizenz über Funktion prüfen
local license = getLicenseFromDB(citizenid, licenseType, true)
if license then
print("=== AKTIVE LIZENZ (über Funktion) ===")
print("Typ: " .. license.license_type)
print("Aktiv: " .. tostring(license.is_active))
print("Status-Check: " .. tostring(isLicenseActive(license)))
print("====================================")
else
print("=== KEINE AKTIVE LIZENZ (über Funktion) ===")
end
else
print("Keine Lizenz gefunden für: " .. citizenid .. " / " .. licenseType)
end
end
end, true)
-- DEBUG COMMAND: Alle Lizenzen eines Spielers anzeigen
RegisterCommand('checkalllicenses', function(source, args, rawCommand)
if source == 0 then -- Console only
if #args < 1 then
print("Usage: checkalllicenses <citizenid>")
return
end
local citizenid = args[1]
-- Direkte DB-Abfrage
local query = "SELECT * FROM player_licenses WHERE citizenid = ? ORDER BY license_type, created_at DESC"
local result = MySQL.query.await(query, {citizenid})
if result and #result > 0 then
print("=== ALLE LIZENZEN FÜR " .. citizenid .. " ===")
for i, license in ipairs(result) do
print(i .. ". " .. license.license_type .. " | Aktiv: " .. tostring(license.is_active) .. " | ID: " .. license.id)
end
print("=========================================")
-- Über Funktion
local activeLicenses = getAllPlayerLicenses(citizenid)
print("=== AKTIVE LIZENZEN (über Funktion) ===")
for i, license in ipairs(activeLicenses) do
print(i .. ". " .. license.license_type .. " | Aktiv: " .. tostring(license.is_active))
end
print("======================================")
else
print("Keine Lizenzen gefunden für: " .. citizenid)
end
end
end, true)
-- DEBUG COMMAND: Lizenz-Status forciert aktualisieren
RegisterCommand('fixlicense', function(source, args, rawCommand)
if source == 0 then -- Console only
if #args < 2 then
print("Usage: fixlicense <citizenid> <license_type>")
return
end
local citizenid = args[1]
local licenseType = args[2]
-- Neueste Lizenz auf aktiv setzen
local query = [[
UPDATE player_licenses
SET is_active = 1
WHERE citizenid = ? AND license_type = ? AND id = (
SELECT id FROM (
SELECT id FROM player_licenses
WHERE citizenid = ? AND license_type = ?
ORDER BY created_at DESC LIMIT 1
) as temp
)
]]
local result = MySQL.query.await(query, {citizenid, licenseType, citizenid, licenseType})
if result then
print("Lizenz-Status aktualisiert für: " .. citizenid .. " / " .. licenseType)
-- Cache invalidieren
invalidateCache(citizenid, licenseType)
-- Prüfen
local license = getLicenseFromDB(citizenid, licenseType, true)
if license then
print("Lizenz ist jetzt aktiv: " .. tostring(license.is_active))
else
print("Lizenz konnte nicht geladen werden")
end
else
print("Fehler beim Aktualisieren der Lizenz")
end
end
end, true)
-- INITIALISIERUNG
CreateThread(function()
debugPrint("License-System Server gestartet (Ausweis-Fix)")
debugPrint("License-System Server gestartet (Status-Fix)")
-- Warten bis QBCore geladen ist
while not QBCore do
@ -827,5 +984,4 @@ function table.count(t)
return count
end
debugPrint("License-System Server vollständig geladen (Ausweis-Fix)")
debugPrint("License-System Server vollständig geladen (Status-Fix)")