Skip to content

Commit e0abe76

Browse files
authored
fix(lib): vehicle spawning reliability
1 parent 58d862e commit e0abe76

File tree

2 files changed

+71
-54
lines changed

2 files changed

+71
-54
lines changed

client/events.lua

+14-19
Original file line numberDiff line numberDiff line change
@@ -206,29 +206,24 @@ RegisterNetEvent('QBCore:Client:OnSharedUpdateMultiple', function(tableName, val
206206
end)
207207

208208
-- Set vehicle props
209-
---@param vehicle number
209+
---@param netId number
210210
---@param props table<any, any>
211-
qbx.entityStateHandler('setVehicleProperties', function(vehicle, _, props)
211+
RegisterNetEvent('qbx_core:client:setVehicleProperties', function(netId, props)
212212
if not props then return end
213-
214-
SetTimeout(0, function()
215-
local state = Entity(vehicle).state
216-
217-
local timeOut = GetGameTimer() + 10000
218-
219-
while state.setVehicleProperties do
220-
if NetworkGetEntityOwner(vehicle) == cache.playerId then
221-
if lib.setVehicleProperties(vehicle, props) then
222-
state:set('setVehicleProperties', nil, true)
223-
end
224-
end
225-
if GetGameTimer() > timeOut then
226-
break
213+
local timeOut = GetGameTimer() + 1000
214+
local vehicle = NetworkGetEntityFromNetworkId(netId)
215+
while true do
216+
if NetworkGetEntityOwner(vehicle) == cache.playerId then
217+
if lib.setVehicleProperties(vehicle, props) then
218+
return
227219
end
228-
229-
Wait(50)
230220
end
231-
end)
221+
if GetGameTimer() > timeOut then
222+
return
223+
end
224+
225+
Wait(50)
226+
end
232227
end)
233228

234229
-- Clear vehicle peds

modules/lib.lua

+57-35
Original file line numberDiff line numberDiff line change
@@ -271,51 +271,73 @@ if isServer then
271271
local vehicleType = GetVehicleType(tempVehicle)
272272
DeleteEntity(tempVehicle)
273273

274-
local veh = CreateVehicleServerSetter(model, vehicleType, coords.x, coords.y, coords.z, coords.w)
275-
while not DoesEntityExist(veh) do Wait(0) end
276-
while GetVehicleNumberPlateText(veh) == '' do Wait(0) end
274+
local attempts = 0
277275

278-
if bucket and bucket > 0 then
279-
exports.qbx_core:SetEntityBucket(veh, bucket)
280-
end
281-
282-
if ped then
283-
SetPedIntoVehicle(ped, veh, -1)
284-
end
276+
local veh, netId
277+
while attempts < 3 do
278+
veh = CreateVehicleServerSetter(model, vehicleType, coords.x, coords.y, coords.z, coords.w)
279+
while not DoesEntityExist(veh) do Wait(0) end
280+
while GetVehicleNumberPlateText(veh) == '' do Wait(0) end
285281

286-
if not pcall(function()
287-
lib.waitFor(function()
288-
local owner = NetworkGetEntityOwner(veh)
289-
if ped then
290-
--- the owner should be transferred to the driver
291-
if owner == NetworkGetEntityOwner(ped) then return true end
292-
else
293-
if owner ~= -1 then return true end
294-
end
295-
end, 'client never set as owner', 5000)
296-
end) then
297-
DeleteEntity(veh)
298-
error('Deleting vehicle which timed out finding an owner')
299-
end
282+
if bucket and bucket > 0 then
283+
exports.qbx_core:SetEntityBucket(veh, bucket)
284+
end
300285

301-
local state = Entity(veh).state
302-
state:set('initVehicle', true, true)
286+
if ped then
287+
SetPedIntoVehicle(ped, veh, -1)
288+
end
303289

304-
if props and type(props) == 'table' and props.plate then
305-
state:set('setVehicleProperties', props, true)
306290
if not pcall(function()
307291
lib.waitFor(function()
308-
if qbx.string.trim(GetVehicleNumberPlateText(veh)) == qbx.string.trim(props.plate) then
309-
return true
292+
local owner = NetworkGetEntityOwner(veh)
293+
if ped then
294+
--- the owner should be transferred to the driver
295+
if owner == NetworkGetEntityOwner(ped) then return true end
296+
else
297+
if owner ~= -1 then return true end
310298
end
311-
end, 'Failed to set vehicle properties within 5 seconds', 5000)
299+
end, 'client never set as owner', 5000)
312300
end) then
313301
DeleteEntity(veh)
314-
error('Deleting vehicle which timed out setting vehicle properties')
302+
error('Deleting vehicle which timed out finding an owner')
315303
end
304+
305+
local state = Entity(veh).state
306+
local owner = NetworkGetEntityOwner(veh)
307+
state:set('initVehicle', true, true)
308+
netId = NetworkGetNetworkIdFromEntity(veh)
309+
if props and type(props) == 'table' and props.plate then
310+
TriggerClientEvent('qbx_core:client:setVehicleProperties', owner, netId, props)
311+
local success = pcall(function()
312+
local plateMatched = false
313+
lib.waitFor(function()
314+
if qbx.string.trim(GetVehicleNumberPlateText(veh)) == qbx.string.trim(props.plate) then
315+
local currentOwner = NetworkGetEntityOwner(veh)
316+
assert(currentOwner == owner, ('Owner changed during vehicle init. expected=%s, actual=%s'):format(owner, currentOwner))
317+
--- check that the plate matches twice, 100ms apart as a bug has been observed in which server side matches but plate is not observed by clients to match
318+
if plateMatched then
319+
return true
320+
end
321+
plateMatched = true
322+
Wait(100)
323+
end
324+
end, 'Failed to set vehicle properties within 1 second', 1000)
325+
end)
326+
if success then
327+
break
328+
else
329+
DeleteEntity(veh)
330+
attempts += 1
331+
end
332+
else
333+
break
334+
end
335+
end
336+
337+
if attempts == 3 then
338+
error('unable to successfully spawn vehicle after 3 attempts')
316339
end
317340

318-
local netId = NetworkGetNetworkIdFromEntity(veh)
319341
exports.qbx_core:EnablePersistence(veh)
320342
return netId, veh
321343
end
@@ -325,8 +347,8 @@ else
325347
---@field scale? integer default: `0.35`
326348
---@field font? integer default: `4`
327349
---@field color? vector4 rgba, white by default
328-
---@field enableDropShadow? boolean
329-
---@field enableOutline? boolean
350+
---@field enableDropShadow? boolean
351+
---@field enableOutline? boolean
330352

331353
---@class LibDrawText2DParams : LibDrawTextParams
332354
---@field coords vector2

0 commit comments

Comments
 (0)