Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(server): full vehicle persistence #621

Open
wants to merge 25 commits into
base: main
Choose a base branch
from

Conversation

CodexisPhantom
Copy link

@CodexisPhantom CodexisPhantom commented Nov 13, 2024

Description

This pull request will add the possibility to qbox users to enable a full vehicle persistence so that cars never despawn even after server restart. I tested this code with 10 people on a clean qbox server.

The convar qbx:enableVehiclePersistence has been modified :

  • 0 : no persistence
  • 1 : old persistence
  • 2 : new persistence

Checklist

  • I have personally loaded this code into an updated Qbox project and checked all of its functionality.
  • My pull request fits the contribution guidelines & code conventions.

server/vehicle-persistence.lua Outdated Show resolved Hide resolved
Copy link
Contributor

@Manason Manason left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Accidentally approved. Ignore this comment.

@CodexisPhantom
Copy link
Author

Hello guys,
Sorry for the time that I took to do this update but I finally did it. Can you check if it's good now @Manason @mafewtm.

@@ -1,3 +1,6 @@
local persistence = GetConvarInt('qbx:enableVehiclePersistence', 0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a breaking change. Either keep the convar as a string an overload the meaning (right now values are 'true' or 'false. We could add 'full' as well. OR add a new true/false convar which controls whether vehicles are persisted between restarts.

Copy link
Member

@D4isDAVID D4isDAVID Dec 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI, values "true" and "false" are interpreted as 1 and 0 respectively by GetConvarInt. But at this point this can actually be replaced by the new GetConvarBool I believe, which is available since artifact 10543 — we require 10731.

Comment on lines 2 to 3
print('Vehicle persistence mode ' .. persistence)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

delete

})
exports.qbx_core:EnablePersistence(veh)
Entity(veh).state:set('vehicleid', id, false)
SetVehicleDoorsLocked(veh, 2)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use qbx_vehiclekeys for this, as setting it directly bypasses checks and such that qbx_vehiclekeys does. Best to make it a config function of core so that people can input other key systems they might be running

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I see, but there's no export in qbx_vehiclekeys to lock a car ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You'll have to create one. Just extract the implementation of qb-vehiclekeys:server:setVehLockState into an export.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okey I see, I'll create a pr in qbx_vehiclekeys then.

model = model,
props = props
})
exports.qbx_core:EnablePersistence(veh)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

qbx.spawnVehicle already sets this.


lib.callback.register('qbx_core:server:getVehiclesToSpawn', function()
local vehicles = {}
local query = 'SELECT id, plate, coords FROM player_vehicles WHERE state = 0'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines 161 to 163
lib.callback.register('qbx_core:server:getVehiclesToSpawn', function()
local vehicles = {}
local query = 'SELECT id, plate, coords FROM player_vehicles WHERE state = 0'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than being queried by every player. This data should be queried on server startup and cached. Then, as vehicles get spawned, the cache gets smaller and smaller.

Comment on lines 177 to 180
RegisterNetEvent('qbx_core:server:spawnVehicle', function(id, coords)
local vehicle = exports.qbx_vehicles:GetPlayerVehicle(id)
if not vehicle then return end
spawnVehicle(coords, id, vehicle.modelName, vehicle.props)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an exploitable event. Needs a server side check. Once a cache exists, you can use it to verify that the id vehicle exists in cache near the specified coords

---@return boolean
local function isVehicleSpawned(plate)
for _, vehicle in pairs(GetGamePool('CVehicle')) do
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GetGamePool returns an array so it's best to use a numeric for loop here instead of pairs.

if not vehicles then return end

for _, vehicle in ipairs(vehicles) do
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

vehicles is an array, use a numeric for loop instead of this.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All done

@Its-Heshi
Copy link

I know this isn’t the right place to ask questions, but I have one. Let’s say a car stopped and I pushed it into the water. If no one is in the seats and a server restart happens at that moment, when I spawn back into the server, will the car still be in the water or not?

What I’m asking is: does this save the car’s coords / and stuff on a restart? or just saves it if someone is in a seat ?

@CodexisPhantom
Copy link
Author

Actually the position is saved only when there's a player in the car.

@Its-Heshi
Copy link

Actually the position is saved only when there's a player in the car.

Ahh. Then I have to look at implementing that on my end. Thanks for the reply.

@CodexisPhantom
Copy link
Author

Not really I can implement that now

@Its-Heshi
Copy link

Its-Heshi commented Jan 24, 2025

Thanks for that. That would be a really cool feat to have on this so no vehicles will be misplaced after a restart., I think you can do that using txAdmin events...

local vehicle = vehicles[i]
if vehicle.coords and vehicle.props and vehicle.props.plate and
not isVehicleSpawned(vehicle.props.plate) then
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This being on the next line makes it look weird with the line below. Better to keep this on one line instead.

@Its-Heshi
Copy link

Its-Heshi commented Jan 29, 2025

Sorry for the ping, @CodexisPhantom

I just remembered something while editing mine. Could you make it so that the vehicle's health and other properties are saved on restart? This way, if the vehicle gets damaged or destroyed while no one is inside, it won’t respawn with the health value saved when someone was in it.

If you can implement vehicle health saving on restart, this should be complete.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants