1
0
Fork 0
forked from Simnation/Main
This commit is contained in:
Nordi98 2025-07-29 23:24:42 +02:00
parent 1301dfa7ad
commit 64fecd2fa0
2 changed files with 267 additions and 240 deletions

View file

@ -26,52 +26,52 @@ function DrawText3D(x, y, z, text)
ClearDrawOrigin() ClearDrawOrigin()
end end
-- Get machine data with proper callback handling -- Get machine data with optimized callback handling
function GetMachineData(entity) function GetMachineData(entity)
local coords = GetEntityCoords(entity) local coords = GetEntityCoords(entity)
local entityId = tostring(coords.x) .. tostring(coords.y) .. tostring(coords.z) local entityId = tostring(coords.x) .. tostring(coords.y) .. tostring(coords.z)
-- Check if we need to refresh the data -- Return cached data if available and not expired
local currentTime = GetGameTimer() local currentTime = GetGameTimer()
if not machineData[entityId] or (currentTime - machineData[entityId].lastCheck > 10000) then if machineData[entityId] and (currentTime - machineData[entityId].lastCheck < 10000) then
-- Initialize with default values return machineData[entityId]
end
-- Initialize with default values
if not machineData[entityId] then
machineData[entityId] = { machineData[entityId] = {
isRegistered = false, isRegistered = false,
canManage = false, canManage = false,
lastCheck = currentTime, lastCheck = currentTime,
checking = true checking = true
} }
else
-- Check if machine is registered machineData[entityId].checking = true
QBCore.Functions.TriggerCallback('vending:server:machineExists', function(exists) machineData[entityId].lastCheck = currentTime
if exists then
machineData[entityId].isRegistered = true
-- Only check management if registered
QBCore.Functions.TriggerCallback('vending:server:canManage', function(result)
machineData[entityId].canManage = result
machineData[entityId].checking = false
end, coords)
else
machineData[entityId].isRegistered = false
machineData[entityId].canManage = false
machineData[entityId].checking = false
end
end, coords)
end end
-- Wait for callbacks to complete if currently checking -- Single callback to get all machine data at once (more efficient)
if machineData[entityId].checking then QBCore.Functions.TriggerCallback('vending:server:getMachineStatus', function(status)
local timeout = 0 if status then
while machineData[entityId].checking and timeout < 50 do machineData[entityId].isRegistered = status.exists
Wait(10) machineData[entityId].canManage = status.canManage
timeout = timeout + 1 else
end machineData[entityId].isRegistered = false
machineData[entityId].canManage = false
-- If timeout reached, set checking to false to avoid deadlock
if timeout >= 50 then
machineData[entityId].checking = false
end end
machineData[entityId].checking = false
end, coords)
-- Short wait for callback to complete
local timeout = 0
while machineData[entityId].checking and timeout < 20 do -- Reduced timeout
Wait(5) -- Shorter wait
timeout = timeout + 1
end
-- If timeout reached, set checking to false to avoid deadlock
if timeout >= 20 then
machineData[entityId].checking = false
end end
return machineData[entityId] return machineData[entityId]
@ -229,49 +229,48 @@ RegisterNetEvent('vending:client:openBuyMenu', function(data)
local entity = data.entity local entity = data.entity
local coords = GetEntityCoords(entity) local coords = GetEntityCoords(entity)
-- Double-check if machine is registered before proceeding -- Fast check using cached data
QBCore.Functions.TriggerCallback('vending:server:machineExists', function(exists) local entityId = tostring(coords.x) .. tostring(coords.y) .. tostring(coords.z)
if not exists then if machineData[entityId] and not machineData[entityId].isRegistered then
QBCore.Functions.Notify('Dieser Automat ist nicht registriert!', 'error') QBCore.Functions.Notify('Dieser Automat ist nicht registriert!', 'error')
return
end
QBCore.Functions.TriggerCallback('vending:server:getStashItems', function(items)
if #items == 0 then
QBCore.Functions.Notify('Dieser Automat ist leer!', 'error')
return return
end end
QBCore.Functions.TriggerCallback('vending:server:getStashItems', function(items) local options = {}
if #items == 0 then
QBCore.Functions.Notify('Dieser Automat ist leer!', 'error') for i = 1, #items do
return local item = items[i]
if item.amount > 0 then
local itemLabel = QBCore.Shared.Items[item.name] and QBCore.Shared.Items[item.name].label or item.name
table.insert(options, {
title = itemLabel,
description = 'Preis: $' .. item.price .. ' | Verfügbar: ' .. item.amount,
icon = 'fas fa-shopping-cart',
onSelect = function()
openQuantityDialog(coords, item.name, item.price, item.amount, itemLabel)
end
})
end end
end
local options = {}
if #options == 0 then
for i = 1, #items do QBCore.Functions.Notify('Keine Artikel verfügbar!', 'error')
local item = items[i] return
if item.amount > 0 then end
local itemLabel = QBCore.Shared.Items[item.name] and QBCore.Shared.Items[item.name].label or item.name
table.insert(options, { lib.registerContext({
title = itemLabel, id = 'vending_buy_menu',
description = 'Preis: $' .. item.price .. ' | Verfügbar: ' .. item.amount, title = 'Verkaufsautomat',
icon = 'fas fa-shopping-cart', options = options
onSelect = function() })
openQuantityDialog(coords, item.name, item.price, item.amount, itemLabel)
end lib.showContext('vending_buy_menu')
})
end
end
if #options == 0 then
QBCore.Functions.Notify('Keine Artikel verfügbar!', 'error')
return
end
lib.registerContext({
id = 'vending_buy_menu',
title = 'Verkaufsautomat',
options = options
})
lib.showContext('vending_buy_menu')
end, coords)
end, coords) end, coords)
end) end)
@ -304,84 +303,83 @@ RegisterNetEvent('vending:client:openOwnerMenu', function(data)
local entity = data.entity local entity = data.entity
local coords = GetEntityCoords(entity) local coords = GetEntityCoords(entity)
-- Double-check if player can manage this machine before proceeding -- Fast check using cached data
QBCore.Functions.TriggerCallback('vending:server:canManage', function(canManage) local entityId = tostring(coords.x) .. tostring(coords.y) .. tostring(coords.z)
if not canManage then if machineData[entityId] and not machineData[entityId].canManage then
QBCore.Functions.Notify('Du hast keine Berechtigung diesen Automaten zu verwalten!', 'error') QBCore.Functions.Notify('Du hast keine Berechtigung diesen Automaten zu verwalten!', 'error')
return
end
QBCore.Functions.TriggerCallback('vending:server:getMachineByCoords', function(machine)
if not machine then
QBCore.Functions.Notify('Automat nicht gefunden!', 'error')
return return
end end
QBCore.Functions.TriggerCallback('vending:server:getMachineByCoords', function(machine) local options = {
if not machine then {
QBCore.Functions.Notify('Automat nicht gefunden!', 'error') title = 'Inventar verwalten',
return description = 'Items hinzufügen/entfernen',
end icon = 'fas fa-box',
onSelect = function()
local options = { TriggerServerEvent('vending:server:openStash', coords)
{ end
title = 'Inventar verwalten', },
description = 'Items hinzufügen/entfernen', {
icon = 'fas fa-box', title = 'Preise festlegen',
onSelect = function() description = 'Verkaufspreise für Items setzen',
TriggerServerEvent('vending:server:openStash', coords) icon = 'fas fa-tags',
end onSelect = function()
}, openPriceMenu(coords)
{ end
title = 'Preise festlegen', },
description = 'Verkaufspreise für Items setzen', {
icon = 'fas fa-tags', title = 'Geld abheben',
onSelect = function() description = 'Verfügbar: $' .. machine.money,
openPriceMenu(coords) icon = 'fas fa-money-bill',
end onSelect = function()
}, openWithdrawMenu(coords, machine.money)
{ end
title = 'Geld abheben', },
description = 'Verfügbar: $' .. machine.money, {
icon = 'fas fa-money-bill', title = 'Statistiken',
onSelect = function() description = 'Verkaufsstatistiken anzeigen',
openWithdrawMenu(coords, machine.money) icon = 'fas fa-chart-bar',
end onSelect = function()
}, openStatsMenu(machine)
{ end
title = 'Statistiken',
description = 'Verkaufsstatistiken anzeigen',
icon = 'fas fa-chart-bar',
onSelect = function()
openStatsMenu(machine)
end
}
} }
}
-- Add manager options only for owner
if machine.isOwner then -- Add manager options only for owner
table.insert(options, { if machine.isOwner then
title = 'Verwalter', table.insert(options, {
description = 'Verwalter hinzufügen/entfernen', title = 'Verwalter',
icon = 'fas fa-users-cog', description = 'Verwalter hinzufügen/entfernen',
onSelect = function() icon = 'fas fa-users-cog',
openManagersMenu(coords) onSelect = function()
end openManagersMenu(coords)
}) end
-- Add sell option only for owner
table.insert(options, {
title = 'Automaten verkaufen',
description = 'Verkaufe den Automaten für ' .. math.floor(Config.VendingMachinePrice * Config.SellBackPercentage / 100) .. '$',
icon = 'fas fa-dollar-sign',
onSelect = function()
sellVendingMachine(coords, machine.id)
end
})
end
lib.registerContext({
id = 'vending_owner_menu',
title = 'Verkaufsautomat Verwaltung',
options = options
}) })
lib.showContext('vending_owner_menu') -- Add sell option only for owner
end, coords) table.insert(options, {
title = 'Automaten verkaufen',
description = 'Verkaufe den Automaten für ' .. math.floor(Config.VendingMachinePrice * Config.SellBackPercentage / 100) .. '$',
icon = 'fas fa-dollar-sign',
onSelect = function()
sellVendingMachine(coords, machine.id)
end
})
end
lib.registerContext({
id = 'vending_owner_menu',
title = 'Verkaufsautomat Verwaltung',
options = options
})
lib.showContext('vending_owner_menu')
end, coords) end, coords)
end) end)
@ -406,43 +404,42 @@ end
-- Open price menu -- Open price menu
function openPriceMenu(coords) function openPriceMenu(coords)
-- Double-check if player can manage this machine before proceeding -- Fast check using cached data
QBCore.Functions.TriggerCallback('vending:server:canManage', function(canManage) local entityId = tostring(coords.x) .. tostring(coords.y) .. tostring(coords.z)
if not canManage then if machineData[entityId] and not machineData[entityId].canManage then
QBCore.Functions.Notify('Du hast keine Berechtigung diesen Automaten zu verwalten!', 'error') QBCore.Functions.Notify('Du hast keine Berechtigung diesen Automaten zu verwalten!', 'error')
return
end
QBCore.Functions.TriggerCallback('vending:server:getStashItems', function(items)
if #items == 0 then
QBCore.Functions.Notify('Keine Items im Automaten!', 'error')
return return
end end
QBCore.Functions.TriggerCallback('vending:server:getStashItems', function(items) local options = {}
if #items == 0 then
QBCore.Functions.Notify('Keine Items im Automaten!', 'error') for i = 1, #items do
return local item = items[i]
end local itemLabel = QBCore.Shared.Items[item.name] and QBCore.Shared.Items[item.name].label or item.name
table.insert(options, {
local options = {} title = itemLabel,
description = 'Aktueller Preis: $' .. item.price,
for i = 1, #items do icon = 'fas fa-tag',
local item = items[i] onSelect = function()
local itemLabel = QBCore.Shared.Items[item.name] and QBCore.Shared.Items[item.name].label or item.name setPriceForItem(coords, item.name, itemLabel)
table.insert(options, { end
title = itemLabel,
description = 'Aktueller Preis: $' .. item.price,
icon = 'fas fa-tag',
onSelect = function()
setPriceForItem(coords, item.name, itemLabel)
end
})
end
lib.registerContext({
id = 'vending_price_menu',
title = 'Preise festlegen',
menu = 'vending_owner_menu',
options = options
}) })
end
lib.showContext('vending_price_menu')
end, coords) lib.registerContext({
id = 'vending_price_menu',
title = 'Preise festlegen',
menu = 'vending_owner_menu',
options = options
})
lib.showContext('vending_price_menu')
end, coords) end, coords)
end end
@ -466,33 +463,32 @@ end
-- Open withdraw menu -- Open withdraw menu
function openWithdrawMenu(coords, availableMoney) function openWithdrawMenu(coords, availableMoney)
-- Double-check if player can manage this machine before proceeding -- Fast check using cached data
QBCore.Functions.TriggerCallback('vending:server:canManage', function(canManage) local entityId = tostring(coords.x) .. tostring(coords.y) .. tostring(coords.z)
if not canManage then if machineData[entityId] and not machineData[entityId].canManage then
QBCore.Functions.Notify('Du hast keine Berechtigung diesen Automaten zu verwalten!', 'error') QBCore.Functions.Notify('Du hast keine Berechtigung diesen Automaten zu verwalten!', 'error')
return return
end end
if availableMoney <= 0 then if availableMoney <= 0 then
QBCore.Functions.Notify('Kein Geld im Automaten!', 'error') QBCore.Functions.Notify('Kein Geld im Automaten!', 'error')
return return
end end
local input = lib.inputDialog('Geld abheben', { local input = lib.inputDialog('Geld abheben', {
{ {
type = 'number', type = 'number',
label = 'Betrag (Verfügbar: $' .. availableMoney .. ')', label = 'Betrag (Verfügbar: $' .. availableMoney .. ')',
description = 'Wie viel möchtest du abheben?', description = 'Wie viel möchtest du abheben?',
required = true, required = true,
min = 1, min = 1,
max = availableMoney max = availableMoney
} }
}) })
if input and input[1] then if input and input[1] then
TriggerServerEvent('vending:server:withdrawMoney', coords, tonumber(input[1])) TriggerServerEvent('vending:server:withdrawMoney', coords, tonumber(input[1]))
end end
end, coords)
end end
-- Open stats menu -- Open stats menu
@ -525,7 +521,7 @@ end
-- Open managers menu -- Open managers menu
function openManagersMenu(coords) function openManagersMenu(coords)
-- Double-check if player is owner of this machine before proceeding -- Fast check for owner status
QBCore.Functions.TriggerCallback('vending:server:isOwner', function(isOwner) QBCore.Functions.TriggerCallback('vending:server:isOwner', function(isOwner)
if not isOwner then if not isOwner then
QBCore.Functions.Notify('Nur der Besitzer kann Verwalter verwalten!', 'error') QBCore.Functions.Notify('Nur der Besitzer kann Verwalter verwalten!', 'error')
@ -598,7 +594,7 @@ end
-- Open add manager menu -- Open add manager menu
function openAddManagerMenu(coords) function openAddManagerMenu(coords)
-- Double-check if player is owner of this machine before proceeding -- Fast check for owner status
QBCore.Functions.TriggerCallback('vending:server:isOwner', function(isOwner) QBCore.Functions.TriggerCallback('vending:server:isOwner', function(isOwner)
if not isOwner then if not isOwner then
QBCore.Functions.Notify('Nur der Besitzer kann Verwalter hinzufügen!', 'error') QBCore.Functions.Notify('Nur der Besitzer kann Verwalter hinzufügen!', 'error')
@ -644,42 +640,39 @@ RegisterNetEvent('vending:client:startRobbery', function(data)
local entity = data.entity local entity = data.entity
local coords = GetEntityCoords(entity) local coords = GetEntityCoords(entity)
-- Double-check if machine is registered and player cannot manage it -- Fast check using cached data
QBCore.Functions.TriggerCallback('vending:server:machineExists', function(exists) local entityId = tostring(coords.x) .. tostring(coords.y) .. tostring(coords.z)
if not exists then if machineData[entityId] then
if not machineData[entityId].isRegistered then
QBCore.Functions.Notify('Dieser Automat ist nicht registriert!', 'error') QBCore.Functions.Notify('Dieser Automat ist nicht registriert!', 'error')
return return
elseif machineData[entityId].canManage then
QBCore.Functions.Notify('Du kannst deinen eigenen Automaten nicht aufbrechen!', 'error')
return
end end
end
QBCore.Functions.TriggerCallback('vending:server:canManage', function(canManage)
if canManage then lib.registerContext({
QBCore.Functions.Notify('Du kannst deinen eigenen Automaten nicht aufbrechen!', 'error') id = 'vending_robbery_confirm',
return title = 'Verkaufsautomat aufbrechen',
end options = {
{
lib.registerContext({ title = 'Aufbrechen',
id = 'vending_robbery_confirm', description = 'Versuche den Automaten aufzubrechen',
title = 'Verkaufsautomat aufbrechen', icon = 'fas fa-mask',
options = { onSelect = function()
{ TriggerServerEvent('vending:server:startRobbery', coords)
title = 'Aufbrechen', end
description = 'Versuche den Automaten aufzubrechen', },
icon = 'fas fa-mask', {
onSelect = function() title = 'Abbrechen',
TriggerServerEvent('vending:server:startRobbery', coords) description = 'Aufbruch abbrechen',
end icon = 'fas fa-times'
}, }
{ }
title = 'Abbrechen', })
description = 'Aufbruch abbrechen',
icon = 'fas fa-times' lib.showContext('vending_robbery_confirm')
}
}
})
lib.showContext('vending_robbery_confirm')
end, coords)
end, coords)
end) end)
-- Start robbery animation and progress -- Start robbery animation and progress
@ -747,7 +740,7 @@ end)
-- Management menu (alternative opening method) -- Management menu (alternative opening method)
RegisterNetEvent('vending:client:openManagement', function(machine) RegisterNetEvent('vending:client:openManagement', function(machine)
-- Double-check if player can manage this machine -- Fast check for management permissions
QBCore.Functions.TriggerCallback('vending:server:canManage', function(canManage) QBCore.Functions.TriggerCallback('vending:server:canManage', function(canManage)
if not canManage then if not canManage then
QBCore.Functions.Notify('Du hast keine Berechtigung diesen Automaten zu verwalten!', 'error') QBCore.Functions.Notify('Du hast keine Berechtigung diesen Automaten zu verwalten!', 'error')
@ -871,4 +864,3 @@ AddEventHandler('onResourceStop', function(resourceName)
-- Nothing to do here, but good to have for completeness -- Nothing to do here, but good to have for completeness
end end
end) end)

View file

@ -712,4 +712,39 @@ QBCore.Commands.Add('vendingdebug', 'Debug vending machines (Admin Only)', {}, f
end end
end, 'admin') end, 'admin')
-- Combined callback for faster machine status checks
QBCore.Functions.CreateCallback('vending:server:getMachineStatus', function(source, cb, coords)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if not Player then
cb(nil)
return
end
local machineId = getMachineIdByCoords(coords)
if not machineId then
cb({exists = false, canManage = false})
return
end
local machine = vendingMachines[machineId]
local canManage = false
-- Check if player is owner
if machine.owner == Player.PlayerData.citizenid then
canManage = true
else
-- Check if player is manager
if machine.managers then
for _, manager in pairs(machine.managers) do
if manager == Player.PlayerData.citizenid then
canManage = true
break
end
end
end
end
cb({exists = true, canManage = canManage})
end)