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 licenseCache = {}
local cacheTimeout = 300000 -- 5 Minuten local cacheTimeout = 300000 -- 5 Minuten
-- Hilfsfunktionen -- Debug-Funktion
local function debugPrint(message) local function debugPrint(message)
if Config.Debug then if Config.Debug then
print("^3[License-System Server] " .. message .. "^7") print("^3[License-System Server] " .. message .. "^7")
@ -24,6 +24,17 @@ local function getPlayerName(src)
return "Unbekannt" return "Unbekannt"
end 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 -- Cache-Funktionen
local function getCachedLicense(citizenid, licenseType) local function getCachedLicense(citizenid, licenseType)
local cacheKey = citizenid .. "_" .. licenseType local cacheKey = citizenid .. "_" .. licenseType
@ -46,20 +57,7 @@ local function setCachedLicense(citizenid, licenseType, data)
debugPrint("Lizenz gecacht: " .. cacheKey) debugPrint("Lizenz gecacht: " .. cacheKey)
end end
-- Berechtigung prüfen -- Spieler-Name aus JSON extrahieren
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)
local function extractPlayerName(charinfo_json) local function extractPlayerName(charinfo_json)
if not charinfo_json then return "Unbekannt" end if not charinfo_json then return "Unbekannt" end
@ -71,7 +69,7 @@ local function extractPlayerName(charinfo_json)
return "Unbekannt" return "Unbekannt"
end end
-- Sichere Datenbankoperationen mit Retry-Mechanismus -- Sichere DB-Operation
local function safeDBOperation(operation, errorMessage, maxRetries) local function safeDBOperation(operation, errorMessage, maxRetries)
maxRetries = maxRetries or 3 maxRetries = maxRetries or 3
local retries = 0 local retries = 0
@ -89,14 +87,14 @@ local function safeDBOperation(operation, errorMessage, maxRetries)
debugPrint("^1Details: " .. tostring(result) .. "^7") debugPrint("^1Details: " .. tostring(result) .. "^7")
return nil return nil
end end
Wait(1000) -- 1 Sekunde warten vor Retry Wait(1000)
end end
end end
return nil return nil
end end
-- Lizenz aus Datenbank abrufen (KORRIGIERT - Collation-sicher) -- KORRIGIERTE Lizenz-Abfrage (Erweiterte Suche)
local function getLicenseFromDB(citizenid, licenseType) local function getLicenseFromDB(citizenid, licenseType)
debugPrint("=== getLicenseFromDB START ===") debugPrint("=== getLicenseFromDB START ===")
debugPrint("CitizenID: " .. tostring(citizenid)) debugPrint("CitizenID: " .. tostring(citizenid))
@ -105,25 +103,53 @@ local function getLicenseFromDB(citizenid, licenseType)
-- Cache prüfen -- Cache prüfen
local cached = getCachedLicense(citizenid, licenseType) local cached = getCachedLicense(citizenid, licenseType)
if cached then if cached then
debugPrint("Lizenz aus Cache geladen")
return cached return cached
end end
-- Einfache Query ohne JOINs um Collation-Probleme zu vermeiden -- ERWEITERTE SUCHE: Erst aktive, dann alle Lizenzen
local query = [[ local queries = {
SELECT * FROM player_licenses -- 1. Suche nach aktiven Lizenzen (is_active = 1)
WHERE citizenid = ? AND license_type = ? AND is_active = 1 {
ORDER BY created_at DESC query = "SELECT * FROM player_licenses WHERE citizenid = ? AND license_type = ? AND is_active = 1 ORDER BY created_at DESC LIMIT 1",
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() local result = safeDBOperation(function()
return MySQL.query.await(query, {citizenid, licenseType}) return MySQL.query.await(queryData.query, {citizenid, licenseType})
end, "Fehler beim Abrufen der Lizenz") end, "Fehler bei " .. queryData.description)
if result and #result > 0 then 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 holderQuery = "SELECT charinfo FROM players WHERE citizenid = ?"
local holderResult = safeDBOperation(function() local holderResult = safeDBOperation(function()
return MySQL.query.await(holderQuery, {citizenid}) return MySQL.query.await(holderQuery, {citizenid})
@ -135,7 +161,7 @@ local function getLicenseFromDB(citizenid, licenseType)
license.holder_name = "Unbekannt" license.holder_name = "Unbekannt"
end end
-- Aussteller-Namen separat abrufen -- Aussteller-Namen abrufen
if license.issued_by then if license.issued_by then
local issuerQuery = "SELECT charinfo FROM players WHERE citizenid = ?" local issuerQuery = "SELECT charinfo FROM players WHERE citizenid = ?"
local issuerResult = safeDBOperation(function() local issuerResult = safeDBOperation(function()
@ -163,16 +189,17 @@ local function getLicenseFromDB(citizenid, licenseType)
license.classes = {} license.classes = {}
end 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 -- In Cache speichern
setCachedLicense(citizenid, licenseType, license) setCachedLicense(citizenid, licenseType, license)
return license return license
end
debugPrint("Keine Lizenz in DB gefunden")
return nil
end end
-- Alle Lizenzen eines Spielers abrufen (KORRIGIERT) -- Alle Lizenzen eines Spielers abrufen (KORRIGIERT)
@ -180,18 +207,34 @@ local function getAllPlayerLicenses(citizenid)
debugPrint("=== getAllPlayerLicenses START ===") debugPrint("=== getAllPlayerLicenses START ===")
debugPrint("CitizenID: " .. tostring(citizenid)) debugPrint("CitizenID: " .. tostring(citizenid))
-- Einfache Query ohne JOINs -- Erweiterte Suche für alle Lizenzen
local query = [[ local queries = {
SELECT * FROM player_licenses -- 1. Aktive Lizenzen
WHERE citizenid = ? AND is_active = 1 "SELECT * FROM player_licenses WHERE citizenid = ? AND is_active = 1 ORDER BY license_type, created_at DESC",
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}) return MySQL.query.await(query, {citizenid})
end, "Fehler beim Abrufen aller Lizenzen") end, "Fehler bei Abfrage " .. i)
if result and #result > 0 then 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 licenses = {}
local seenTypes = {} local seenTypes = {}
@ -241,19 +284,20 @@ local function getAllPlayerLicenses(citizenid)
license.classes = {} license.classes = {}
end end
-- is_active standardisieren
if license.is_active == nil then
license.is_active = 1
end
table.insert(licenses, license) table.insert(licenses, license)
end end
end end
debugPrint("Gefundene Lizenzen: " .. #licenses) debugPrint("Verarbeitete Lizenzen: " .. #licenses)
return licenses return licenses
end
debugPrint("Keine Lizenzen gefunden")
return {}
end end
-- Lizenz in Datenbank speichern (KORRIGIERT - DateTime-Fix) -- Lizenz in Datenbank speichern (KORRIGIERT)
local function saveLicenseToDB(citizenid, licenseType, issuedBy, classes) local function saveLicenseToDB(citizenid, licenseType, issuedBy, classes)
debugPrint("=== saveLicenseToDB START ===") debugPrint("=== saveLicenseToDB START ===")
debugPrint("CitizenID: " .. tostring(citizenid)) debugPrint("CitizenID: " .. tostring(citizenid))
@ -266,7 +310,7 @@ local function saveLicenseToDB(citizenid, licenseType, issuedBy, classes)
return false return false
end end
-- Spieler-Name für das name-Feld abrufen -- Spieler-Name abrufen
local holderQuery = "SELECT charinfo FROM players WHERE citizenid = ?" local holderQuery = "SELECT charinfo FROM players WHERE citizenid = ?"
local holderResult = safeDBOperation(function() local holderResult = safeDBOperation(function()
return MySQL.query.await(holderQuery, {citizenid}) return MySQL.query.await(holderQuery, {citizenid})
@ -295,16 +339,14 @@ local function saveLicenseToDB(citizenid, licenseType, issuedBy, classes)
return MySQL.query.await(deactivateQuery, {citizenid, licenseType}) return MySQL.query.await(deactivateQuery, {citizenid, licenseType})
end, "Fehler beim Deaktivieren alter Lizenz") end, "Fehler beim Deaktivieren alter Lizenz")
-- Neue Lizenz einfügen (KORRIGIERT - DateTime als BIGINT oder korrektes Format) -- Neue Lizenz einfügen
local insertQuery = [[ local insertQuery = [[
INSERT INTO player_licenses INSERT INTO player_licenses
(citizenid, license_type, name, issue_date, expire_date, issued_by, is_active, classes, created_at) (citizenid, license_type, name, issue_date, expire_date, issued_by, is_active, classes, created_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
]] ]]
-- created_at als BIGINT (Unix Timestamp) oder als DATETIME local createdAt = os.time() -- Unix Timestamp
local createdAt = os.time() -- Unix Timestamp für BIGINT
-- Alternativ für DATETIME: local createdAt = os.date("%Y-%m-%d %H:%M:%S")
local insertData = { local insertData = {
citizenid, citizenid,
@ -313,7 +355,7 @@ local function saveLicenseToDB(citizenid, licenseType, issuedBy, classes)
issueDate, issueDate,
expireDate, expireDate,
issuedBy, issuedBy,
1, 1, -- is_active = 1
classesJson, classesJson,
createdAt createdAt
} }
@ -345,7 +387,7 @@ local function revokeLicenseInDB(citizenid, licenseType)
debugPrint("CitizenID: " .. tostring(citizenid)) debugPrint("CitizenID: " .. tostring(citizenid))
debugPrint("LicenseType: " .. tostring(licenseType)) 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() local result = safeDBOperation(function()
return MySQL.query.await(query, {citizenid, licenseType}) return MySQL.query.await(query, {citizenid, licenseType})
@ -390,7 +432,7 @@ CreateThread(function()
end end
end) end)
-- EVENT HANDLER: Lizenz anfordern -- EVENT HANDLER: Lizenz anfordern (KORRIGIERT für Ausweis-Anzeige)
RegisterNetEvent('license-system:server:requestLicense', function(targetId) RegisterNetEvent('license-system:server:requestLicense', function(targetId)
local src = source local src = source
debugPrint("=== Event: requestLicense ===") debugPrint("=== Event: requestLicense ===")
@ -411,34 +453,39 @@ RegisterNetEvent('license-system:server:requestLicense', function(targetId)
local citizenid = targetPlayer.PlayerData.citizenid 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 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) local license = getLicenseFromDB(citizenid, licenseType)
if license and license.is_active == 1 then if license then
foundLicense = { foundLicense = {
license = license, license = license,
config = Config.LicenseTypes[licenseType] config = Config.LicenseTypes[licenseType]
} }
debugPrint("Lizenz gefunden: " .. licenseType)
break break
end end
end end
end
if foundLicense then if foundLicense then
debugPrint("Sende Lizenz an Client: " .. foundLicense.license.license_type) debugPrint("Sende Lizenz an Client: " .. foundLicense.license.license_type)
TriggerClientEvent('license-system:client:receiveLicense', src, foundLicense) TriggerClientEvent('license-system:client:receiveLicense', src, foundLicense)
else else
debugPrint("Keine aktive Lizenz gefunden") debugPrint("Keine Lizenz gefunden")
TriggerClientEvent('license-system:client:receiveLicense', src, nil) TriggerClientEvent('license-system:client:receiveLicense', src, nil)
end end
end) end)
-- EVENT HANDLER: Eigene Lizenz anfordern -- EVENT HANDLER: Eigene Lizenz anfordern (KORRIGIERT)
RegisterNetEvent('license-system:server:requestMyLicense', function(licenseType) RegisterNetEvent('license-system:server:requestMyLicense', function(licenseType)
local src = source local src = source
debugPrint("=== Event: requestMyLicense ===") debugPrint("=== Event: requestMyLicense ===")
debugPrint("Source: " .. src .. ", LicenseType: " .. licenseType) debugPrint("Source: " .. src .. ", LicenseType: " .. tostring(licenseType))
local Player = QBCore.Functions.GetPlayer(src) local Player = QBCore.Functions.GetPlayer(src)
if not Player then if not Player then
@ -448,9 +495,16 @@ RegisterNetEvent('license-system:server:requestMyLicense', function(licenseType)
end end
local citizenid = Player.PlayerData.citizenid 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) local license = getLicenseFromDB(citizenid, licenseType)
if license and license.is_active == 1 then if license then
local licenseData = { local licenseData = {
license = license, license = license,
config = Config.LicenseTypes[licenseType] config = Config.LicenseTypes[licenseType]
@ -518,7 +572,7 @@ RegisterNetEvent('license-system:server:issueLicense', function(targetId, licens
local targetCitizenId = targetPlayer.PlayerData.citizenid local targetCitizenId = targetPlayer.PlayerData.citizenid
local issuerCitizenId = issuerPlayer.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) local existingLicense = getLicenseFromDB(targetCitizenId, licenseType)
if existingLicense and existingLicense.is_active == 1 then if existingLicense and existingLicense.is_active == 1 then
@ -613,12 +667,12 @@ RegisterNetEvent('license-system:server:revokeLicense', function(targetId, licen
end end
end) end)
-- EXPORT FUNKTIONEN -- EXPORT FUNKTIONEN (KORRIGIERT)
exports('hasLicense', function(citizenid, licenseType) exports('hasLicense', function(citizenid, licenseType)
if not citizenid or not licenseType then return false end if not citizenid or not licenseType then return false end
local license = getLicenseFromDB(citizenid, licenseType) 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) end)
exports('issueLicense', function(citizenid, licenseType, issuedBy, classes) exports('issueLicense', function(citizenid, licenseType, issuedBy, classes)
@ -646,9 +700,67 @@ exports('getPlayerLicense', function(citizenid, licenseType)
return getLicenseFromDB(citizenid, licenseType) return getLicenseFromDB(citizenid, licenseType)
end) 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 -- INITIALISIERUNG
CreateThread(function() CreateThread(function()
debugPrint("License-System Server gestartet (Collation & DateTime Fix)") debugPrint("License-System Server gestartet (Ausweis-Fix)")
-- Warten bis QBCore geladen ist -- Warten bis QBCore geladen ist
while not QBCore do while not QBCore do
@ -689,7 +801,7 @@ RegisterCommand('licensestats', function(source, args, rawCommand)
print("=== LICENSE SYSTEM STATS ===") print("=== LICENSE SYSTEM STATS ===")
print("Cache Entries: " .. cacheCount) 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("============================") print("============================")
end end
end, true) end, true)
@ -706,4 +818,14 @@ RegisterCommand('licenseclearcache', function(source, args, rawCommand)
end end
end, true) 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)")