1
0
Fork 0
forked from Simnation/Main

Update main.lua

This commit is contained in:
Nordi98 2025-08-04 09:05:35 +02:00
parent 23aa5c33e7
commit e4f7b961d5

View file

@ -4,7 +4,7 @@ local QBCore = exports['qb-core']:GetCoreObject()
local licenseCache = {}
local cacheTimeout = 300000 -- 5 Minuten
-- Hilfsfunktionen
-- Debug-Funktion
local function debugPrint(message)
if Config.Debug then
print("^3[License-System Server] " .. message .. "^7")
@ -24,6 +24,17 @@ local function getPlayerName(src)
return "Unbekannt"
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
return Config.AuthorizedJobs[job.name] or false
end
-- Cache-Funktionen
local function getCachedLicense(citizenid, licenseType)
local cacheKey = citizenid .. "_" .. licenseType
@ -46,20 +57,7 @@ local function setCachedLicense(citizenid, licenseType, data)
debugPrint("Lizenz gecacht: " .. cacheKey)
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
-- Spieler-Name aus JSON extrahieren (Collation-sicher)
-- Spieler-Name aus JSON extrahieren
local function extractPlayerName(charinfo_json)
if not charinfo_json then return "Unbekannt" end
@ -71,7 +69,7 @@ local function extractPlayerName(charinfo_json)
return "Unbekannt"
end
-- Sichere Datenbankoperationen mit Retry-Mechanismus
-- Sichere DB-Operation
local function safeDBOperation(operation, errorMessage, maxRetries)
maxRetries = maxRetries or 3
local retries = 0
@ -89,14 +87,14 @@ local function safeDBOperation(operation, errorMessage, maxRetries)
debugPrint("^1Details: " .. tostring(result) .. "^7")
return nil
end
Wait(1000) -- 1 Sekunde warten vor Retry
Wait(1000)
end
end
return nil
end
-- Lizenz aus Datenbank abrufen (KORRIGIERT - Collation-sicher)
-- KORRIGIERTE Lizenz-Abfrage (Erweiterte Suche)
local function getLicenseFromDB(citizenid, licenseType)
debugPrint("=== getLicenseFromDB START ===")
debugPrint("CitizenID: " .. tostring(citizenid))
@ -105,25 +103,53 @@ local function getLicenseFromDB(citizenid, licenseType)
-- Cache prüfen
local cached = getCachedLicense(citizenid, licenseType)
if cached then
debugPrint("Lizenz aus Cache geladen")
return cached
end
-- Einfache Query ohne JOINs um Collation-Probleme zu vermeiden
local query = [[
SELECT * FROM player_licenses
WHERE citizenid = ? AND license_type = ? AND is_active = 1
ORDER BY created_at DESC
LIMIT 1
]]
-- 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"
}
}
local license = nil
for i, queryData in ipairs(queries) do
debugPrint("Versuche Query " .. i .. ": " .. queryData.description)
local result = safeDBOperation(function()
return MySQL.query.await(query, {citizenid, licenseType})
end, "Fehler beim Abrufen der Lizenz")
return MySQL.query.await(queryData.query, {citizenid, licenseType})
end, "Fehler bei " .. queryData.description)
if result and #result > 0 then
local license = result[1]
license = result[1]
debugPrint("Lizenz gefunden mit Query " .. i .. ": " .. queryData.description)
break
else
debugPrint("Keine Lizenz mit Query " .. i .. " gefunden")
end
end
-- Spieler-Namen separat abrufen
if not license then
debugPrint("^1Keine Lizenz in DB gefunden für " .. citizenid .. " / " .. licenseType .. "^7")
return nil
end
-- Spieler-Namen abrufen
local holderQuery = "SELECT charinfo FROM players WHERE citizenid = ?"
local holderResult = safeDBOperation(function()
return MySQL.query.await(holderQuery, {citizenid})
@ -135,7 +161,7 @@ local function getLicenseFromDB(citizenid, licenseType)
license.holder_name = "Unbekannt"
end
-- Aussteller-Namen separat abrufen
-- Aussteller-Namen abrufen
if license.issued_by then
local issuerQuery = "SELECT charinfo FROM players WHERE citizenid = ?"
local issuerResult = safeDBOperation(function()
@ -163,16 +189,17 @@ local function getLicenseFromDB(citizenid, licenseType)
license.classes = {}
end
debugPrint("Lizenz aus DB geladen: " .. license.license_type)
-- is_active standardisieren (falls nicht gesetzt)
if license.is_active == nil then
license.is_active = 1
end
debugPrint("Lizenz erfolgreich geladen: " .. license.license_type .. " (Active: " .. tostring(license.is_active) .. ")")
-- 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)
@ -180,18 +207,34 @@ local function getAllPlayerLicenses(citizenid)
debugPrint("=== getAllPlayerLicenses START ===")
debugPrint("CitizenID: " .. tostring(citizenid))
-- Einfache Query ohne JOINs
local query = [[
SELECT * FROM player_licenses
WHERE citizenid = ? AND is_active = 1
ORDER BY license_type, created_at DESC
]]
-- 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"
}
local result = safeDBOperation(function()
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 beim Abrufen aller Lizenzen")
end, "Fehler bei Abfrage " .. i)
if result and #result > 0 then
debugPrint("Lizenzen gefunden mit Abfrage " .. i .. ": " .. #result .. " Einträge")
break
end
end
if not result or #result == 0 then
debugPrint("Keine Lizenzen gefunden für: " .. citizenid)
return {}
end
local licenses = {}
local seenTypes = {}
@ -241,19 +284,20 @@ local function getAllPlayerLicenses(citizenid)
license.classes = {}
end
-- is_active standardisieren
if license.is_active == nil then
license.is_active = 1
end
table.insert(licenses, license)
end
end
debugPrint("Gefundene Lizenzen: " .. #licenses)
debugPrint("Verarbeitete Lizenzen: " .. #licenses)
return licenses
end
debugPrint("Keine Lizenzen gefunden")
return {}
end
-- Lizenz in Datenbank speichern (KORRIGIERT - DateTime-Fix)
-- Lizenz in Datenbank speichern (KORRIGIERT)
local function saveLicenseToDB(citizenid, licenseType, issuedBy, classes)
debugPrint("=== saveLicenseToDB START ===")
debugPrint("CitizenID: " .. tostring(citizenid))
@ -266,7 +310,7 @@ local function saveLicenseToDB(citizenid, licenseType, issuedBy, classes)
return false
end
-- Spieler-Name für das name-Feld abrufen
-- Spieler-Name abrufen
local holderQuery = "SELECT charinfo FROM players WHERE citizenid = ?"
local holderResult = safeDBOperation(function()
return MySQL.query.await(holderQuery, {citizenid})
@ -295,16 +339,14 @@ local function saveLicenseToDB(citizenid, licenseType, issuedBy, classes)
return MySQL.query.await(deactivateQuery, {citizenid, licenseType})
end, "Fehler beim Deaktivieren alter Lizenz")
-- Neue Lizenz einfügen (KORRIGIERT - DateTime als BIGINT oder korrektes Format)
-- 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 (?, ?, ?, ?, ?, ?, ?, ?, ?)
]]
-- created_at als BIGINT (Unix Timestamp) oder als DATETIME
local createdAt = os.time() -- Unix Timestamp für BIGINT
-- Alternativ für DATETIME: local createdAt = os.date("%Y-%m-%d %H:%M:%S")
local createdAt = os.time() -- Unix Timestamp
local insertData = {
citizenid,
@ -313,7 +355,7 @@ local function saveLicenseToDB(citizenid, licenseType, issuedBy, classes)
issueDate,
expireDate,
issuedBy,
1,
1, -- is_active = 1
classesJson,
createdAt
}
@ -345,7 +387,7 @@ local function revokeLicenseInDB(citizenid, licenseType)
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 query = "UPDATE player_licenses SET is_active = 0 WHERE citizenid = ? AND license_type = ?"
local result = safeDBOperation(function()
return MySQL.query.await(query, {citizenid, licenseType})
@ -390,7 +432,7 @@ CreateThread(function()
end
end)
-- EVENT HANDLER: Lizenz anfordern
-- EVENT HANDLER: Lizenz anfordern (KORRIGIERT für Ausweis-Anzeige)
RegisterNetEvent('license-system:server:requestLicense', function(targetId)
local src = source
debugPrint("=== Event: requestLicense ===")
@ -411,34 +453,39 @@ RegisterNetEvent('license-system:server:requestLicense', function(targetId)
local citizenid = targetPlayer.PlayerData.citizenid
-- Erste verfügbare Lizenz finden
-- PRIORITÄT: Erst nach Ausweis suchen, dann andere Lizenzen
local licenseTypes = {"id_card", "driver_license", "weapon_license", "pilot_license"}
local foundLicense = nil
for licenseType, _ in pairs(Config.LicenseTypes) do
for _, licenseType in ipairs(licenseTypes) do
if Config.LicenseTypes[licenseType] then
local license = getLicenseFromDB(citizenid, licenseType)
if license and license.is_active == 1 then
if license then
foundLicense = {
license = license,
config = Config.LicenseTypes[licenseType]
}
debugPrint("Lizenz gefunden: " .. licenseType)
break
end
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")
debugPrint("Keine Lizenz gefunden")
TriggerClientEvent('license-system:client:receiveLicense', src, nil)
end
end)
-- EVENT HANDLER: Eigene Lizenz anfordern
-- EVENT HANDLER: Eigene Lizenz anfordern (KORRIGIERT)
RegisterNetEvent('license-system:server:requestMyLicense', function(licenseType)
local src = source
debugPrint("=== Event: requestMyLicense ===")
debugPrint("Source: " .. src .. ", LicenseType: " .. licenseType)
debugPrint("Source: " .. src .. ", LicenseType: " .. tostring(licenseType))
local Player = QBCore.Functions.GetPlayer(src)
if not Player then
@ -448,9 +495,16 @@ RegisterNetEvent('license-system:server:requestMyLicense', function(licenseType)
end
local citizenid = Player.PlayerData.citizenid
-- Falls kein spezifischer Typ angegeben, suche nach Ausweis
if not licenseType or licenseType == "" then
licenseType = "id_card"
debugPrint("Kein Lizenztyp angegeben, verwende: " .. licenseType)
end
local license = getLicenseFromDB(citizenid, licenseType)
if license and license.is_active == 1 then
if license then
local licenseData = {
license = license,
config = Config.LicenseTypes[licenseType]
@ -518,7 +572,7 @@ RegisterNetEvent('license-system:server:issueLicense', function(targetId, licens
local targetCitizenId = targetPlayer.PlayerData.citizenid
local issuerCitizenId = issuerPlayer.PlayerData.citizenid
-- Prüfen ob Lizenz bereits existiert
-- Prüfen ob aktive Lizenz bereits existiert
local existingLicense = getLicenseFromDB(targetCitizenId, licenseType)
if existingLicense and existingLicense.is_active == 1 then
@ -613,12 +667,12 @@ RegisterNetEvent('license-system:server:revokeLicense', function(targetId, licen
end
end)
-- EXPORT FUNKTIONEN
-- EXPORT FUNKTIONEN (KORRIGIERT)
exports('hasLicense', function(citizenid, licenseType)
if not citizenid or not licenseType then return false end
local license = getLicenseFromDB(citizenid, licenseType)
return license and license.is_active == 1
return license ~= nil and (license.is_active == 1 or license.is_active == nil)
end)
exports('issueLicense', function(citizenid, licenseType, issuedBy, classes)
@ -646,9 +700,67 @@ exports('getPlayerLicense', function(citizenid, licenseType)
return getLicenseFromDB(citizenid, licenseType)
end)
-- DEBUG COMMAND: Lizenz manuell erstellen
RegisterCommand('createlicense', function(source, args, rawCommand)
if source == 0 then -- Console only
if #args < 2 then
print("Usage: createlicense <citizenid> <license_type>")
return
end
local citizenid = args[1]
local licenseType = args[2]
if not Config.LicenseTypes[licenseType] then
print("Unbekannter Lizenztyp: " .. licenseType)
return
end
local success = saveLicenseToDB(citizenid, licenseType, 'console', {})
if success then
print("Lizenz erfolgreich erstellt: " .. licenseType .. " für " .. citizenid)
else
print("Fehler beim Erstellen der Lizenz")
end
end
end, true)
-- DEBUG COMMAND: Lizenz prüfen
RegisterCommand('checklicense', function(source, args, rawCommand)
if source == 0 then -- Console only
if #args < 2 then
print("Usage: checklicense <citizenid> <license_type>")
return
end
local citizenid = args[1]
local licenseType = args[2]
local license = getLicenseFromDB(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("=====================")
else
print("Keine Lizenz gefunden für: " .. citizenid .. " / " .. licenseType)
end
end
end, true)
-- INITIALISIERUNG
CreateThread(function()
debugPrint("License-System Server gestartet (Collation & DateTime Fix)")
debugPrint("License-System Server gestartet (Ausweis-Fix)")
-- Warten bis QBCore geladen ist
while not QBCore do
@ -689,7 +801,7 @@ RegisterCommand('licensestats', function(source, args, rawCommand)
print("=== LICENSE SYSTEM STATS ===")
print("Cache Entries: " .. cacheCount)
print("Config License Types: " .. (Config.LicenseTypes and #Config.LicenseTypes or 0))
print("Config License Types: " .. (Config.LicenseTypes and table.count(Config.LicenseTypes) or 0))
print("============================")
end
end, true)
@ -706,4 +818,14 @@ RegisterCommand('licenseclearcache', function(source, args, rawCommand)
end
end, true)
debugPrint("License-System Server vollständig geladen (Collation & DateTime Fix)")
-- Hilfsfunktion für table.count
function table.count(t)
local count = 0
for _ in pairs(t) do
count = count + 1
end
return count
end
debugPrint("License-System Server vollständig geladen (Ausweis-Fix)")