1
0
Fork 0
forked from Simnation/Main
Main/resources/[carscripts]/nordi_rental/server.lua
2025-07-26 03:54:08 +02:00

374 lines
15 KiB
Lua

local QBCore = exports['qb-core']:GetCoreObject()
local activeRentals = {}
-- Füge einen Schlüssel für ein Mietfahrzeug hinzu
function AddRentalKey(citizenid, plate, model)
MySQL.Async.execute('INSERT INTO vehicle_keys (owner, plate, count) VALUES (?, ?, ?)', {
citizenid,
plate,
1
}, function(rowsChanged)
if rowsChanged > 0 then
print("Schlüssel für Mietfahrzeug hinzugefügt: " .. plate .. " für Spieler " .. citizenid)
end
end)
end
-- Entferne einen Schlüssel für ein Mietfahrzeug
function RemoveRentalKey(citizenid, plate)
MySQL.Async.execute('DELETE FROM vehicle_keys WHERE owner = ? AND plate = ?', {
citizenid,
plate
}, function(rowsChanged)
if rowsChanged > 0 then
print("Schlüssel für Mietfahrzeug entfernt: " .. plate .. " für Spieler " .. citizenid)
end
end)
end
-- Lade alle aktiven Mietfahrzeuge beim Serverstart
Citizen.CreateThread(function()
Wait(5000) -- Warte, bis die Datenbank bereit ist
MySQL.Async.fetchAll('SELECT * FROM vehicle_rentals WHERE returned = FALSE', {}, function(results)
if results and #results > 0 then
print("Lade " .. #results .. " aktive Mietfahrzeuge...")
for _, rental in ipairs(results) do
activeRentals[rental.vehicle_plate] = rental
-- Stelle sicher, dass für jedes Mietfahrzeug ein Schlüssel existiert
MySQL.Async.fetchAll('SELECT * FROM vehicle_keys WHERE owner = ? AND plate = ?', {
rental.citizenid,
rental.vehicle_plate
}, function(keyResults)
if not keyResults or #keyResults == 0 then
-- Füge einen Schlüssel hinzu, wenn keiner existiert
AddRentalKey(rental.citizenid, rental.vehicle_plate, rental.vehicle_model)
end
end)
end
-- Benachrichtige alle Clients, dass sie die Fahrzeuge spawnen sollen
TriggerClientEvent('vehiclerental:client:loadRentals', -1, results)
end
end)
end)
-- Aktualisiere die Position eines Mietfahrzeugs
RegisterServerEvent('vehiclerental:server:updatePosition')
AddEventHandler('vehiclerental:server:updatePosition', function(plate, position, rotation)
if not plate or not position then return end
-- Aktualisiere in der Datenbank
MySQL.Async.execute('UPDATE vehicle_rentals SET posX = ?, posY = ?, posZ = ?, rotX = ?, rotY = ?, rotZ = ?, lastUpdated = CURRENT_TIMESTAMP WHERE vehicle_plate = ? AND returned = FALSE', {
position.x, position.y, position.z,
rotation.x, rotation.y, rotation.z,
plate
})
-- Aktualisiere im Cache
if activeRentals[plate] then
activeRentals[plate].posX = position.x
activeRentals[plate].posY = position.y
activeRentals[plate].posZ = position.z
activeRentals[plate].rotX = rotation.x
activeRentals[plate].rotY = rotation.y
activeRentals[plate].rotZ = rotation.z
end
end)
-- Fahrzeug mieten
QBCore.Functions.CreateCallback('vehiclerental:server:rentVehicle', function(source, cb, data)
local Player = QBCore.Functions.GetPlayer(source)
if not Player then return cb(false) end
local totalCost = data.pricePerHour * data.hours
local currentTime = os.time()
local endTime = currentTime + (data.hours * 3600)
-- Zahlung prüfen und abziehen
local paymentSuccess = false
if Config.UseOkokBanking then
local bankMoney = exports['okokBanking']:GetAccount(Player.PlayerData.citizenid)
if bankMoney and bankMoney >= totalCost then
exports['okokBanking']:RemoveMoney(Player.PlayerData.citizenid, totalCost)
paymentSuccess = true
end
else
if Player.Functions.RemoveMoney('cash', totalCost) then
paymentSuccess = true
end
end
if not paymentSuccess then
TriggerClientEvent('QBCore:Notify', source, 'Nicht genug Geld!', 'error')
return cb(false)
end
-- Fahrzeug in Datenbank eintragen
MySQL.Async.insert('INSERT INTO vehicle_rentals (citizenid, vehicle_model, vehicle_plate, rental_location, start_time, end_time, price_per_hour) VALUES (?, ?, ?, ?, ?, ?, ?)', {
Player.PlayerData.citizenid,
data.vehicleModel,
data.plate,
data.locationId,
currentTime,
endTime,
data.pricePerHour
}, function(rentalId)
-- Füge das Fahrzeug zum aktiven Cache hinzu
activeRentals[data.plate] = {
id = rentalId,
citizenid = Player.PlayerData.citizenid,
vehicle_model = data.vehicleModel,
vehicle_plate = data.plate,
rental_location = data.locationId,
start_time = currentTime,
end_time = endTime,
price_per_hour = data.pricePerHour,
returned = false
}
-- Füge einen Schlüssel für das Mietfahrzeug hinzu
AddRentalKey(Player.PlayerData.citizenid, data.plate, data.vehicleModel)
TriggerClientEvent('QBCore:Notify', source, 'Fahrzeug erfolgreich gemietet für $' .. totalCost, 'success')
cb(true)
end)
end)
-- Fahrzeug zurückgeben
QBCore.Functions.CreateCallback('vehiclerental:server:returnVehicle', function(source, cb, plate)
local Player = QBCore.Functions.GetPlayer(source)
if not Player then return cb(false) end
MySQL.Async.fetchAll('SELECT * FROM vehicle_rentals WHERE citizenid = ? AND vehicle_plate = ? AND returned = FALSE', {
Player.PlayerData.citizenid,
plate
}, function(result)
if not result[1] then
TriggerClientEvent('QBCore:Notify', source, 'Kein aktives Mietverhältnis für dieses Fahrzeug gefunden!', 'error')
return cb(false)
end
local rental = result[1]
local currentTime = os.time()
local penalty = 0
-- Strafe berechnen wenn verspätet
if currentTime > rental.end_time then
local hoursLate = math.ceil((currentTime - rental.end_time) / 3600)
penalty = hoursLate * Config.PenaltyPerHour
end
-- Strafe abziehen falls vorhanden
if penalty > 0 then
local penaltyPaid = false
if Config.UseOkokBanking then
local bankMoney = exports['okokBanking']:GetAccount(Player.PlayerData.citizenid)
if bankMoney and bankMoney >= penalty then
exports['okokBanking']:RemoveMoney(Player.PlayerData.citizenid, penalty)
penaltyPaid = true
end
else
if Player.Functions.RemoveMoney('cash', penalty) then
penaltyPaid = true
end
end
if penaltyPaid then
TriggerClientEvent('QBCore:Notify', source, 'Verspätungsstrafe von $' .. penalty .. ' wurde abgezogen!', 'error')
else
TriggerClientEvent('QBCore:Notify', source, 'Nicht genug Geld für Verspätungsstrafe!', 'error')
return cb(false)
end
end
-- Mietverhältnis als zurückgegeben markieren
MySQL.Async.execute('UPDATE vehicle_rentals SET returned = TRUE, penalty_paid = ? WHERE id = ?', {
penalty > 0,
rental.id
})
-- Aus dem aktiven Cache entfernen
activeRentals[plate] = nil
-- Entferne den Schlüssel für das Mietfahrzeug
RemoveRentalKey(Player.PlayerData.citizenid, plate)
-- Benachrichtige alle Clients, dass das Fahrzeug zurückgegeben wurde
TriggerClientEvent('vehiclerental:client:vehicleReturned', -1, plate)
TriggerClientEvent('QBCore:Notify', source, 'Fahrzeug erfolgreich zurückgegeben!', 'success')
cb(true)
end)
end)
-- Spieler Mietverhältnisse abrufen
QBCore.Functions.CreateCallback('vehiclerental:server:getPlayerRentals', function(source, cb)
local Player = QBCore.Functions.GetPlayer(source)
if not Player then return cb(nil) end
MySQL.Async.fetchAll('SELECT * FROM vehicle_rentals WHERE citizenid = ? AND returned = FALSE', {
Player.PlayerData.citizenid
}, function(result)
if not result or #result == 0 then
return cb(nil)
end
local currentTime = os.time()
for i = 1, #result do
-- Berechne verbleibende Zeit auf dem Server
result[i].timeLeft = result[i].end_time - currentTime
result[i].isOverdue = result[i].timeLeft < 0
-- Formatiere die Zeit für die Anzeige
if result[i].isOverdue then
local hoursOverdue = math.ceil(math.abs(result[i].timeLeft) / 3600)
result[i].timeText = "(Überfällig um " .. hoursOverdue .. " Stunden)"
else
local hoursLeft = math.floor(result[i].timeLeft / 3600)
local minutesLeft = math.floor((result[i].timeLeft % 3600) / 60)
result[i].timeText = "(" .. hoursLeft .. "h " .. minutesLeft .. "m verbleibend)"
end
end
cb(result)
end)
end)
-- Befehl für Mietzeit
QBCore.Commands.Add('mietzeit', 'Zeige deine aktuelle Mietzeit an', {}, false, function(source, args)
local Player = QBCore.Functions.GetPlayer(source)
if not Player then return end
MySQL.Async.fetchAll('SELECT * FROM vehicle_rentals WHERE citizenid = ? AND returned = FALSE', {
Player.PlayerData.citizenid
}, function(result)
if not result or #result == 0 then
TriggerClientEvent('QBCore:Notify', source, 'Du hast keine aktiven Mietverhältnisse!', 'error')
return
end
for i = 1, #result do
local rental = result[i]
local currentTime = os.time()
local timeLeft = rental.end_time - currentTime
local timeText = ""
if timeLeft < 0 then
local hoursOverdue = math.ceil(math.abs(timeLeft) / 3600)
timeText = "Überfällig um " .. hoursOverdue .. " Stunden"
TriggerClientEvent('QBCore:Notify', source, rental.vehicle_model .. " (" .. rental.vehicle_plate .. "): " .. timeText, 'error')
else
local hoursLeft = math.floor(timeLeft / 3600)
local minutesLeft = math.floor((timeLeft % 3600) / 60)
timeText = hoursLeft .. "h " .. minutesLeft .. "m verbleibend"
TriggerClientEvent('QBCore:Notify', source, rental.vehicle_model .. " (" .. rental.vehicle_plate .. "): " .. timeText, 'primary')
end
end
end)
end)
-- Regelmäßige Überprüfung auf überfällige Fahrzeuge
Citizen.CreateThread(function()
while true do
Citizen.Wait(60000) -- Überprüfe jede Minute
local currentTime = os.time()
local overdueVehicles = {}
-- Überprüfe alle aktiven Mietfahrzeuge
for plate, rental in pairs(activeRentals) do
if currentTime > rental.end_time + (Config.MaxOverdueHours * 3600) then
-- Fahrzeug ist zu lange überfällig, markiere es als zurückgegeben
MySQL.Async.execute('UPDATE vehicle_rentals SET returned = TRUE, penalty_paid = TRUE WHERE vehicle_plate = ? AND returned = FALSE', {
plate
})
-- Entferne den Schlüssel für das Mietfahrzeug
RemoveRentalKey(rental.citizenid, plate)
-- Füge es zur Liste der zu entfernenden Fahrzeuge hinzu
table.insert(overdueVehicles, plate)
end
end
-- Entferne überfällige Fahrzeuge aus dem Cache
for _, plate in ipairs(overdueVehicles) do
activeRentals[plate] = nil
-- Benachrichtige alle Clients, dass das Fahrzeug entfernt werden soll
TriggerClientEvent('vehiclerental:client:vehicleReturned', -1, plate)
end
end
end)
-- Spieler verbindet sich
RegisterNetEvent('QBCore:Server:PlayerLoaded')
AddEventHandler('QBCore:Server:PlayerLoaded', function()
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if not Player then return end
-- Sende dem Spieler seine aktiven Mietfahrzeuge
MySQL.Async.fetchAll('SELECT * FROM vehicle_rentals WHERE citizenid = ? AND returned = FALSE', {
Player.PlayerData.citizenid
}, function(results)
if results and #results > 0 then
-- Stelle sicher, dass für jedes Mietfahrzeug ein Schlüssel existiert
for _, rental in ipairs(results) do
-- Prüfe, ob bereits ein Schlüssel existiert
MySQL.Async.fetchAll('SELECT * FROM vehicle_keys WHERE owner = ? AND plate = ?', {
Player.PlayerData.citizenid,
rental.vehicle_plate
}, function(keyResults)
if not keyResults or #keyResults == 0 then
-- Füge einen Schlüssel hinzu, wenn keiner existiert
AddRentalKey(Player.PlayerData.citizenid, rental.vehicle_plate, rental.vehicle_model)
end
end)
end
TriggerClientEvent('vehiclerental:client:loadRentals', src, results)
end
end)
end)
-- Exportiere Funktionen für andere Ressourcen
exports('GetActiveRentals', function(citizenid)
local playerRentals = {}
for plate, rental in pairs(activeRentals) do
if rental.citizenid == citizenid then
table.insert(playerRentals, rental)
end
end
return playerRentals
end)
-- Event für andere Ressourcen
RegisterNetEvent('vehiclerental:server:checkRentalKeys')
AddEventHandler('vehiclerental:server:checkRentalKeys', function()
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if not Player then return end
-- Hole alle aktiven Mietverhältnisse des Spielers
MySQL.Async.fetchAll('SELECT * FROM vehicle_rentals WHERE citizenid = ? AND returned = FALSE', {
Player.PlayerData.citizenid
}, function(rentals)
if rentals and #rentals > 0 then
for _, rental in ipairs(rentals) do
-- Prüfe, ob ein Schlüssel existiert
MySQL.Async.fetchAll('SELECT * FROM vehicle_keys WHERE owner = ? AND plate = ?', {
Player.PlayerData.citizenid,
rental.vehicle_plate
}, function(keyResults)
if not keyResults or #keyResults == 0 then
-- Füge einen Schlüssel hinzu, wenn keiner existiert
AddRentalKey(Player.PlayerData.citizenid, rental.vehicle_plate, rental.vehicle_model)
end
end)
end
end
end)
end)