1
0
Fork 0
forked from Simnation/Main

Update client.lua

This commit is contained in:
Nordi98 2025-07-29 23:10:02 +02:00
parent fdc0882b51
commit 1973b32054

View file

@ -26,51 +26,55 @@ function DrawText3D(x, y, z, text)
ClearDrawOrigin() ClearDrawOrigin()
end end
-- Cache machine data to avoid constant callbacks -- Get machine data with proper callback handling
function GetMachineData(entity) function GetMachineData(entity)
local entityId = NetworkGetNetworkIdFromEntity(entity) local coords = GetEntityCoords(entity)
local entityId = tostring(coords.x) .. tostring(coords.y) .. tostring(coords.z)
if not machineData[entityId] then -- Check if we need to refresh the data
local coords = GetEntityCoords(entity) local currentTime = GetGameTimer()
local isRegistered = false if not machineData[entityId] or (currentTime - machineData[entityId].lastCheck > 10000) then
local canManage = false -- Initialize with default values
machineData[entityId] = {
isRegistered = false,
canManage = false,
lastCheck = currentTime,
checking = true
}
-- Check if machine is registered -- Check if machine is registered
QBCore.Functions.TriggerCallback('vending:server:machineExists', function(exists) QBCore.Functions.TriggerCallback('vending:server:machineExists', function(exists)
isRegistered = exists if exists then
machineData[entityId].isRegistered = true
-- Only check management if registered
if isRegistered then -- Only check management if registered
QBCore.Functions.TriggerCallback('vending:server:canManage', function(result) QBCore.Functions.TriggerCallback('vending:server:canManage', function(result)
canManage = result machineData[entityId].canManage = result
machineData[entityId].checking = false
-- Store data in cache
machineData[entityId] = {
isRegistered = isRegistered,
canManage = canManage,
lastCheck = GetGameTimer()
}
end, coords) end, coords)
else else
-- Store data in cache machineData[entityId].isRegistered = false
machineData[entityId] = { machineData[entityId].canManage = false
isRegistered = false, machineData[entityId].checking = false
canManage = false,
lastCheck = GetGameTimer()
}
end end
end, coords) end, coords)
end
-- Wait for callbacks to complete
-- Wait for callbacks to complete if currently checking
if machineData[entityId].checking then
local timeout = 0 local timeout = 0
while not machineData[entityId] and timeout < 50 do while machineData[entityId].checking and timeout < 50 do
Wait(10) Wait(10)
timeout = timeout + 1 timeout = timeout + 1
end end
-- If timeout reached, set checking to false to avoid deadlock
if timeout >= 50 then
machineData[entityId].checking = false
end
end end
-- Return cached data or default return machineData[entityId]
return machineData[entityId] or {isRegistered = false, canManage = false}
end end
-- Clear cache periodically -- Clear cache periodically
@ -110,7 +114,7 @@ CreateThread(function()
foundMachine = true foundMachine = true
nearbyMachine = obj nearbyMachine = obj
-- Get machine data from cache -- Get machine data
local data = GetMachineData(obj) local data = GetMachineData(obj)
-- Display appropriate text based on machine status -- Display appropriate text based on machine status
@ -177,9 +181,6 @@ RegisterNetEvent('vending:client:refreshTargets', function()
machineData = {} machineData = {}
end) end)
-- Keep all the existing event handlers and functions below this point
-- They don't need to be modified since they work with ox_lib
-- Buy vending machine -- Buy vending machine
RegisterNetEvent('vending:client:buyMachine', function(data) RegisterNetEvent('vending:client:buyMachine', function(data)
local entity = data.entity local entity = data.entity
@ -207,6 +208,9 @@ RegisterNetEvent('vending:client:buyMachine', function(data)
icon = 'fas fa-check', icon = 'fas fa-check',
onSelect = function() onSelect = function()
TriggerServerEvent('vending:server:registerMachine', coords, prop) TriggerServerEvent('vending:server:registerMachine', coords, prop)
-- Clear cache for this machine
local entityId = tostring(coords.x) .. tostring(coords.y) .. tostring(coords.z)
machineData[entityId] = nil
end end
}, },
{ {
@ -225,41 +229,49 @@ RegisterNetEvent('vending:client:openBuyMenu', function(data)
local entity = data.entity local entity = data.entity
local coords = GetEntityCoords(entity) local coords = GetEntityCoords(entity)
QBCore.Functions.TriggerCallback('vending:server:getStashItems', function(items) -- Double-check if machine is registered before proceeding
if #items == 0 then QBCore.Functions.TriggerCallback('vending:server:machineExists', function(exists)
QBCore.Functions.Notify('Dieser Automat ist leer!', 'error') if not exists then
QBCore.Functions.Notify('Dieser Automat ist nicht registriert!', 'error')
return return
end end
local options = {} QBCore.Functions.TriggerCallback('vending:server:getStashItems', function(items)
if #items == 0 then
for i = 1, #items do QBCore.Functions.Notify('Dieser Automat ist leer!', 'error')
local item = items[i] return
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
QBCore.Functions.Notify('Keine Artikel verfügbar!', 'error') for i = 1, #items do
return local item = items[i]
end if item.amount > 0 then
local itemLabel = QBCore.Shared.Items[item.name] and QBCore.Shared.Items[item.name].label or item.name
lib.registerContext({ table.insert(options, {
id = 'vending_buy_menu', title = itemLabel,
title = 'Verkaufsautomat', description = 'Preis: $' .. item.price .. ' | Verfügbar: ' .. item.amount,
options = options icon = 'fas fa-shopping-cart',
}) onSelect = function()
openQuantityDialog(coords, item.name, item.price, item.amount, itemLabel)
lib.showContext('vending_buy_menu') end
})
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)
@ -292,76 +304,84 @@ RegisterNetEvent('vending:client:openOwnerMenu', function(data)
local entity = data.entity local entity = data.entity
local coords = GetEntityCoords(entity) local coords = GetEntityCoords(entity)
QBCore.Functions.TriggerCallback('vending:server:getMachineByCoords', function(machine) -- Double-check if player can manage this machine before proceeding
if not machine then QBCore.Functions.TriggerCallback('vending:server:canManage', function(canManage)
QBCore.Functions.Notify('Automat nicht gefunden!', 'error') if not canManage then
QBCore.Functions.Notify('Du hast keine Berechtigung diesen Automaten zu verwalten!', 'error')
return return
end end
local options = { QBCore.Functions.TriggerCallback('vending:server:getMachineByCoords', function(machine)
{ if not machine then
title = 'Inventar verwalten', QBCore.Functions.Notify('Automat nicht gefunden!', 'error')
description = 'Items hinzufügen/entfernen', return
icon = 'fas fa-box', end
onSelect = function()
TriggerServerEvent('vending:server:openStash', coords) local options = {
end {
}, title = 'Inventar verwalten',
{ description = 'Items hinzufügen/entfernen',
title = 'Preise festlegen', icon = 'fas fa-box',
description = 'Verkaufspreise für Items setzen', onSelect = function()
icon = 'fas fa-tags', TriggerServerEvent('vending:server:openStash', coords)
onSelect = function() end
openPriceMenu(coords) },
end {
}, title = 'Preise festlegen',
{ description = 'Verkaufspreise für Items setzen',
title = 'Geld abheben', icon = 'fas fa-tags',
description = 'Verfügbar: $' .. machine.money, onSelect = function()
icon = 'fas fa-money-bill', openPriceMenu(coords)
onSelect = function() end
openWithdrawMenu(coords, machine.money) },
end {
}, title = 'Geld abheben',
{ description = 'Verfügbar: $' .. machine.money,
title = 'Statistiken', icon = 'fas fa-money-bill',
description = 'Verkaufsstatistiken anzeigen', onSelect = function()
icon = 'fas fa-chart-bar', openWithdrawMenu(coords, machine.money)
onSelect = function() end
openStatsMenu(machine) },
end {
title = 'Statistiken',
description = 'Verkaufsstatistiken anzeigen',
icon = 'fas fa-chart-bar',
onSelect = function()
openStatsMenu(machine)
end
}
} }
}
-- Add manager options only for owner
-- Add manager options only for owner if machine.isOwner then
if machine.isOwner then table.insert(options, {
table.insert(options, { title = 'Verwalter',
title = 'Verwalter', description = 'Verwalter hinzufügen/entfernen',
description = 'Verwalter hinzufügen/entfernen', icon = 'fas fa-users-cog',
icon = 'fas fa-users-cog', onSelect = function()
onSelect = function() openManagersMenu(coords)
openManagersMenu(coords) end
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
}) })
-- Add sell option only for owner lib.showContext('vending_owner_menu')
table.insert(options, { end, coords)
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)
@ -378,40 +398,51 @@ function sellVendingMachine(coords, machineId)
if input and input[1] then if input and input[1] then
TriggerServerEvent('vending:server:sellMachine', coords, machineId) TriggerServerEvent('vending:server:sellMachine', coords, machineId)
-- Clear cache for this machine
local entityId = tostring(coords.x) .. tostring(coords.y) .. tostring(coords.z)
machineData[entityId] = nil
end end
end end
-- Open price menu -- Open price menu
function openPriceMenu(coords) function openPriceMenu(coords)
QBCore.Functions.TriggerCallback('vending:server:getStashItems', function(items) -- Double-check if player can manage this machine before proceeding
if #items == 0 then QBCore.Functions.TriggerCallback('vending:server:canManage', function(canManage)
QBCore.Functions.Notify('Keine Items im Automaten!', 'error') if not canManage then
QBCore.Functions.Notify('Du hast keine Berechtigung diesen Automaten zu verwalten!', 'error')
return return
end end
local options = {} QBCore.Functions.TriggerCallback('vending:server:getStashItems', function(items)
if #items == 0 then
for i = 1, #items do QBCore.Functions.Notify('Keine Items im Automaten!', 'error')
local item = items[i] return
local itemLabel = QBCore.Shared.Items[item.name] and QBCore.Shared.Items[item.name].label or item.name end
table.insert(options, {
title = itemLabel, local options = {}
description = 'Aktueller Preis: $' .. item.price,
icon = 'fas fa-tag', for i = 1, #items do
onSelect = function() local item = items[i]
setPriceForItem(coords, item.name, itemLabel) local itemLabel = QBCore.Shared.Items[item.name] and QBCore.Shared.Items[item.name].label or item.name
end table.insert(options, {
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')
lib.registerContext({ end, coords)
id = 'vending_price_menu',
title = 'Preise festlegen',
menu = 'vending_owner_menu',
options = options
})
lib.showContext('vending_price_menu')
end, coords) end, coords)
end end
@ -435,25 +466,33 @@ end
-- Open withdraw menu -- Open withdraw menu
function openWithdrawMenu(coords, availableMoney) function openWithdrawMenu(coords, availableMoney)
if availableMoney <= 0 then -- Double-check if player can manage this machine before proceeding
QBCore.Functions.Notify('Kein Geld im Automaten!', 'error') QBCore.Functions.TriggerCallback('vending:server:canManage', function(canManage)
return if not canManage then
end QBCore.Functions.Notify('Du hast keine Berechtigung diesen Automaten zu verwalten!', 'error')
return
local input = lib.inputDialog('Geld abheben', { end
{
type = 'number', if availableMoney <= 0 then
label = 'Betrag (Verfügbar: $' .. availableMoney .. ')', QBCore.Functions.Notify('Kein Geld im Automaten!', 'error')
description = 'Wie viel möchtest du abheben?', return
required = true, end
min = 1,
max = availableMoney local input = lib.inputDialog('Geld abheben', {
} {
}) type = 'number',
label = 'Betrag (Verfügbar: $' .. availableMoney .. ')',
if input and input[1] then description = 'Wie viel möchtest du abheben?',
TriggerServerEvent('vending:server:withdrawMoney', coords, tonumber(input[1])) required = true,
end min = 1,
max = availableMoney
}
})
if input and input[1] then
TriggerServerEvent('vending:server:withdrawMoney', coords, tonumber(input[1]))
end
end, coords)
end end
-- Open stats menu -- Open stats menu
@ -486,102 +525,118 @@ end
-- Open managers menu -- Open managers menu
function openManagersMenu(coords) function openManagersMenu(coords)
-- Get current managers -- Double-check if player is owner of this machine before proceeding
QBCore.Functions.TriggerCallback('vending:server:getManagers', function(managers) QBCore.Functions.TriggerCallback('vending:server:isOwner', function(isOwner)
local options = { if not isOwner then
{ QBCore.Functions.Notify('Nur der Besitzer kann Verwalter verwalten!', 'error')
title = 'Verwalter hinzufügen', return
description = 'Neuen Verwalter hinzufügen',
icon = 'fas fa-user-plus',
onSelect = function()
openAddManagerMenu(coords)
end
}
}
-- Add existing managers with remove option
if #managers > 0 then
for i = 1, #managers do
local manager = managers[i]
table.insert(options, {
title = manager.name,
description = manager.online and 'Online' or 'Offline',
icon = manager.online and 'fas fa-circle text-success' or 'fas fa-circle text-danger',
onSelect = function()
lib.registerContext({
id = 'manager_options',
title = 'Verwalter: ' .. manager.name,
menu = 'managers_menu',
options = {
{
title = 'Entfernen',
description = 'Verwalter entfernen',
icon = 'fas fa-user-minus',
onSelect = function()
TriggerServerEvent('vending:server:removeManager', coords, manager.citizenid)
Wait(500)
openManagersMenu(coords) -- Refresh the menu
end
}
}
})
lib.showContext('manager_options')
end
})
end
else
table.insert(options, {
title = 'Keine Verwalter',
description = 'Es sind keine Verwalter vorhanden',
icon = 'fas fa-info-circle',
disabled = true
})
end end
lib.registerContext({ -- Get current managers
id = 'managers_menu', QBCore.Functions.TriggerCallback('vending:server:getManagers', function(managers)
title = 'Verwalter verwalten', local options = {
menu = 'vending_owner_menu', {
options = options title = 'Verwalter hinzufügen',
}) description = 'Neuen Verwalter hinzufügen',
icon = 'fas fa-user-plus',
lib.showContext('managers_menu') onSelect = function()
openAddManagerMenu(coords)
end
}
}
-- Add existing managers with remove option
if #managers > 0 then
for i = 1, #managers do
local manager = managers[i]
table.insert(options, {
title = manager.name,
description = manager.online and 'Online' or 'Offline',
icon = manager.online and 'fas fa-circle text-success' or 'fas fa-circle text-danger',
onSelect = function()
lib.registerContext({
id = 'manager_options',
title = 'Verwalter: ' .. manager.name,
menu = 'managers_menu',
options = {
{
title = 'Entfernen',
description = 'Verwalter entfernen',
icon = 'fas fa-user-minus',
onSelect = function()
TriggerServerEvent('vending:server:removeManager', coords, manager.citizenid)
Wait(500)
openManagersMenu(coords) -- Refresh the menu
end
}
}
})
lib.showContext('manager_options')
end
})
end
else
table.insert(options, {
title = 'Keine Verwalter',
description = 'Es sind keine Verwalter vorhanden',
icon = 'fas fa-info-circle',
disabled = true
})
end
lib.registerContext({
id = 'managers_menu',
title = 'Verwalter verwalten',
menu = 'vending_owner_menu',
options = options
})
lib.showContext('managers_menu')
end, coords)
end, coords) end, coords)
end end
-- Open add manager menu -- Open add manager menu
function openAddManagerMenu(coords) function openAddManagerMenu(coords)
QBCore.Functions.TriggerCallback('vending:server:getOnlinePlayers', function(players) -- Double-check if player is owner of this machine before proceeding
if #players == 0 then QBCore.Functions.TriggerCallback('vending:server:isOwner', function(isOwner)
QBCore.Functions.Notify('Keine Spieler online!', 'error') if not isOwner then
QBCore.Functions.Notify('Nur der Besitzer kann Verwalter hinzufügen!', 'error')
return return
end end
local options = {} QBCore.Functions.TriggerCallback('vending:server:getOnlinePlayers', function(players)
if #players == 0 then
for i = 1, #players do QBCore.Functions.Notify('Keine Spieler online!', 'error')
local player = players[i] return
table.insert(options, { end
title = player.name,
description = 'ID: ' .. player.id, local options = {}
icon = 'fas fa-user',
onSelect = function() for i = 1, #players do
TriggerServerEvent('vending:server:addManager', coords, player.id) local player = players[i]
Wait(500) table.insert(options, {
openManagersMenu(coords) -- Refresh the menu title = player.name,
end description = 'ID: ' .. player.id,
icon = 'fas fa-user',
onSelect = function()
TriggerServerEvent('vending:server:addManager', coords, player.id)
Wait(500)
openManagersMenu(coords) -- Refresh the menu
end
})
end
lib.registerContext({
id = 'add_manager_menu',
title = 'Verwalter hinzufügen',
menu = 'managers_menu',
options = options
}) })
end
lib.showContext('add_manager_menu')
lib.registerContext({ end)
id = 'add_manager_menu', end, coords)
title = 'Verwalter hinzufügen',
menu = 'managers_menu',
options = options
})
lib.showContext('add_manager_menu')
end)
end end
-- Robbery menu -- Robbery menu
@ -589,27 +644,42 @@ RegisterNetEvent('vending:client:startRobbery', function(data)
local entity = data.entity local entity = data.entity
local coords = GetEntityCoords(entity) local coords = GetEntityCoords(entity)
lib.registerContext({ -- Double-check if machine is registered and player cannot manage it
id = 'vending_robbery_confirm', QBCore.Functions.TriggerCallback('vending:server:machineExists', function(exists)
title = 'Verkaufsautomat aufbrechen', if not exists then
options = { QBCore.Functions.Notify('Dieser Automat ist nicht registriert!', 'error')
{ return
title = 'Aufbrechen', end
description = 'Versuche den Automaten aufzubrechen',
icon = 'fas fa-mask', QBCore.Functions.TriggerCallback('vending:server:canManage', function(canManage)
onSelect = function() if canManage then
TriggerServerEvent('vending:server:startRobbery', coords) QBCore.Functions.Notify('Du kannst deinen eigenen Automaten nicht aufbrechen!', 'error')
end return
}, end
{
title = 'Abbrechen', lib.registerContext({
description = 'Aufbruch abbrechen', id = 'vending_robbery_confirm',
icon = 'fas fa-times' title = 'Verkaufsautomat aufbrechen',
} options = {
} {
}) title = 'Aufbrechen',
description = 'Versuche den Automaten aufzubrechen',
lib.showContext('vending_robbery_confirm') icon = 'fas fa-mask',
onSelect = function()
TriggerServerEvent('vending:server:startRobbery', coords)
end
},
{
title = 'Abbrechen',
description = 'Aufbruch abbrechen',
icon = 'fas fa-times'
}
}
})
lib.showContext('vending_robbery_confirm')
end, coords)
end, coords)
end) end)
-- Start robbery animation and progress -- Start robbery animation and progress
@ -677,30 +747,38 @@ end)
-- Management menu (alternative opening method) -- Management menu (alternative opening method)
RegisterNetEvent('vending:client:openManagement', function(machine) RegisterNetEvent('vending:client:openManagement', function(machine)
lib.registerContext({ -- Double-check if player can manage this machine
id = 'vending_management', QBCore.Functions.TriggerCallback('vending:server:canManage', function(canManage)
title = 'Verkaufsautomat #' .. machine.id, if not canManage then
options = { QBCore.Functions.Notify('Du hast keine Berechtigung diesen Automaten zu verwalten!', 'error')
{ return
title = 'Inventar öffnen', end
description = 'Items hinzufügen oder entfernen',
icon = 'fas fa-box', lib.registerContext({
onSelect = function() id = 'vending_management',
TriggerServerEvent('vending:server:openStash', machine.coords) title = 'Verkaufsautomat #' .. machine.id,
end options = {
}, {
{ title = 'Inventar öffnen',
title = 'Einnahmen: $' .. machine.money, description = 'Items hinzufügen oder entfernen',
description = 'Geld abheben', icon = 'fas fa-box',
icon = 'fas fa-money-bill', onSelect = function()
onSelect = function() TriggerServerEvent('vending:server:openStash', machine.coords)
openWithdrawMenu(machine.coords, machine.money) end
end },
{
title = 'Einnahmen: $' .. machine.money,
description = 'Geld abheben',
icon = 'fas fa-money-bill',
onSelect = function()
openWithdrawMenu(machine.coords, machine.money)
end
}
} }
} })
})
lib.showContext('vending_management')
lib.showContext('vending_management') end, machine.coords)
end) end)
-- Debug command to check props -- Debug command to check props
@ -760,3 +838,37 @@ RegisterCommand('vendingdebug', function()
end end
end, coords) end, coords)
end, false) end, false)
-- Clear cache command for debugging
RegisterCommand('clearvendingcache', function()
machineData = {}
QBCore.Functions.Notify('Vending machine cache cleared', 'success')
end, false)
-- Event handler for when player loads
RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function()
-- Clear cache when player loads
machineData = {}
end)
-- Event handler for when player unloads
RegisterNetEvent('QBCore:Client:OnPlayerUnload', function()
-- Clear cache when player unloads
machineData = {}
end)
-- Event handler for resource start
AddEventHandler('onResourceStart', function(resourceName)
if resourceName == GetCurrentResourceName() then
-- Clear cache when resource starts
machineData = {}
end
end)
-- Event handler for resource stop
AddEventHandler('onResourceStop', function(resourceName)
if resourceName == GetCurrentResourceName() then
-- Nothing to do here, but good to have for completeness
end
end)