Skip to content

vehicle paintjob reset on respawn, SeedCookie timing, and NPC vehicle death events - #1213

Open
Aesir1337 wants to merge 3 commits into
openmultiplayer:masterfrom
Aesir1337:issue-fixes
Open

vehicle paintjob reset on respawn, SeedCookie timing, and NPC vehicle death events#1213
Aesir1337 wants to merge 3 commits into
openmultiplayer:masterfrom
Aesir1337:issue-fixes

Conversation

@Aesir1337

Copy link
Copy Markdown

1. Reset paintjob on vehicle respawn (closes #1212)

Vehicle paintjob was not being cleared in _respawn() alongside other visual properties (mods, colours). After respawn the paintjob persisted, causing a desync between the vehicle's visual state and its server-side data.

Fix: Added paintJob = 0 to Vehicle::_respawn() in vehicle.cpp.


2. Move SeedCookie after rakNetServer.Start() (closes #1211)

SeedCookie was being set before the RakNet server started, which could cause connection failures in certain scenarios.

Fix: Moved SeedCookie call to after rakNetServer.Start().


3. Fix OnVehicleDeath / OnVehicleSpawn not firing for NPC-driven vehicles (closes #1196)

NPCs don’t send exit/death RPCs, so vehicles stay permanently occupied. This blocks the onTick respawn logic and prevents OnVehicleDeath/Spawn, leaving vehicles in a zombie state.

Fix: In VehiclesComponent::onTick() (vehicles_impl.hpp), detect the case where a dead vehicle's only occupant is an NPC driver and bypass the occupation check. The existing _respawn() already clears the driver pointer, so no further changes are needed.

Vehicle paintjob was not being cleared in _respawn() while all other
modifications (mods, colours, damage) were properly reset, causing the
paintjob to persist after vehicle respawn.

Fixes openmultiplayer#1212
… failures

RakPeer::Start() internally calls RakPeer::Disconnect() which resets
RakNet internal state. SeedCookie() was called before Start(), meaning
the seeded cookie was discarded. Clients connecting in the window
between server start and the first onTick() re-seed would fail cookie
validation and have their packets silently ignored (issue openmultiplayer#1211).

Also adds an explanatory comment to the paintjob reset fix.
NPC players have no game client to send vehicle exit or death RPCs,
so their vehicles remained permanently "occupied" after dying. The
onTick death/respawn path was gated behind !isOccupied(), causing
OnVehicleDeath and OnVehicleSpawn to never fire for NPC-driven vehicles.

Detect the NPC-only occupied dead case and bypass the occupation check,
allowing death events and respawn to proceed normally (respawn already
clears the driver pointer via _respawn()).

Fixes openmultiplayer#1196
@Joey251

Joey251 commented Apr 22, 2026

Copy link
Copy Markdown

@Aesir1337 Thanks a lot, I implemented your SeedCookie solution and so far I haven’t noticed any complaints about connection issues.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR addresses three server-side vehicle/network correctness issues: (1) ensuring vehicle paintjobs don’t persist across respawn, (2) fixing a rare connection-handshake failure by seeding RakNet cookies after server start, and (3) restoring OnVehicleDeath/OnVehicleSpawn behavior for NPC-driven vehicles by preventing “permanently occupied” zombie states.

Changes:

  • Reset Vehicle::paintJob during _respawn() to avoid visual/server-state desync after respawn.
  • Move SAMPRakNet::SeedCookie() to after rakNetServer.Start() to avoid Start()-induced state resets discarding the seeded cookie.
  • In VehiclesComponent::onTick(), treat dead vehicles occupied only by an NPC as effectively unoccupied so death/respawn logic can run.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
Server/Components/Vehicles/vehicles_impl.hpp Adds NPC-only occupation bypass to allow death/respawn logic to run for dead NPC-driven vehicles.
Server/Components/Vehicles/vehicle.cpp Resets paintjob during vehicle respawn to avoid paintjob persistence/desync.
Server/Components/LegacyNetwork/legacy_network_impl.cpp Moves cookie seeding to occur after RakNet server start to prevent handshake failures.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +595 to +598
IPlayer* vehicleDriver = vehicle->getDriver();
bool deadNPCOnly = vehicle->isDead() && vehicleDriver != nullptr && vehicleDriver->isBot() && vehicle->getPassengers().empty();

if (!vehicle->isOccupied() || deadNPCOnly)
Comment on lines 708 to 712
timeOfSpawn = Time::now();
mods.fill(0);
// paintJob was not reset here unlike mods and colours, causing it to persist after vehicle respawn (issue #1212)
paintJob = 0;
doorDamage = 0;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

4 participants