Sync persistent projectiles (satchels, teargas, molotov) on stream-in#4986
Open
TheCrazy17 wants to merge 6 commits into
Open
Sync persistent projectiles (satchels, teargas, molotov) on stream-in#4986TheCrazy17 wants to merge 6 commits into
TheCrazy17 wants to merge 6 commits into
Conversation
…ho come into range later Packet_ProjectileSync only broadcasts a projectile's creation once, to whoever is in range at that instant. Satchel charges, teargas clouds and molotov fires stick around in the world afterwards, so a player who was out of range when one appeared never sees it, even after walking right up to it. Server now remembers these per-owner, and periodically checks if any other player has come within sync range, sending them the original creation packet when they do. Satchels are tracked until detonated/destroyed explicitly; teargas/molotov entries expire after 20s, comfortably outlasting their visual effect. Fixes multitheftauto#369 Fixes multitheftauto#368
…ed in yet Packet_ProjectileSync's client handler silently drops the projectile if CClientProjectileManager::Create() can't get a game-layer entity for the creator (pPed->GetGameEntity() null), which happens whenever the thrower's ped/vehicle hasn't streamed into the GTA world yet for the receiving client - e.g. right after connecting, or right after coming into range of a satchel/ teargas/molotov that was planted earlier while out of view (see the ProcessProjectileStreamIn resync added previously for issues multitheftauto#369/multitheftauto#368). Queue the creation and keep retrying every pulse for up to a minute instead, giving the engine time to stream the creator in.
…playing the throw Late stream-in (just connected, or just came into range of a satchel planted earlier) resent the original throw packet - origin + velocity - which replays the whole toss client-side. Since physics replay isn't perfectly deterministic, the satchel can visibly fly through the air again and occasionally settle somewhere slightly different (floating, or in a different spot) than the one everyone else has been looking at. The owning client now reports the actual resting position once CClientProjectile::CorrectPhysics finishes settling the satchel (new PACKET_ID_PROJECTILE_REST_POSITION packet). The server swaps the tracked persistent-projectile entry over to that position with zero velocity/force, so any later stream-in places it directly instead of re-throwing it. Scoped to satchel charges only - they're the only persistent projectile type with no lifespan of its own, so a wrong replay stays wrong indefinitely instead of being a momentary blip like teargas/molotov. multitheftauto#369 multitheftauto#368
…anded on Placing a satchel at its resting position via the new rest-position resync still let normal physics run on it client-side, which caused two more visible issues once it had to materialize at an arbitrary point in the world instead of being thrown into it: - The area's collision may not be streamed in yet when a player walks up to a satchel that's been sitting there for a while, so it fell through the floor under gravity until something already-loaded caught it. - A satchel stuck to a vehicle/ped only got a one-off absolute position, so it stayed behind, detached, the moment that vehicle/ped moved. The owning client now also reports what the satchel stuck to (if anything), via CProjectile::GetAttachedEntity()/GetAttachedOffsets() - the same native attach GTA already uses for satchels. The server stores that as a position relative to the attached entity (reusing the m_OriginID/m_vecOrigin mechanism CProjectileSyncPacket already has for heat-seeking rockets). On creation, a resynced satchel (recognised by zero velocity/force, which a live throw never has) is pinned with SetStaticWaitingForCollision() - the same engine flag used for script-placed objects whose collision isn't loaded yet - and natively re-attached via AttachEntityToEntity() if it was stuck to something, so it keeps following it afterwards exactly like the original. multitheftauto#369 multitheftauto#368
…e entity Re-attaching a resynced satchel with a zero offset always snapped it to the attached vehicle/ped's origin, so a satchel stuck to e.g. the hood instead showed up at the vehicle's centre for anyone who streamed in late. The owning client now also reports GTA's own native attach offset (CProjectile::GetAttachedOffsets() - the same position/rotation pair AttachEntityToEntity expects) when the satchel settles, and the resync carries it through end to end: - CProjectileRestPositionPacket (client -> server) gains the offset fields. - CGame::Packet_ProjectileRestPosition stores them on the tracked entry. - CProjectileSyncPacket (server -> client) gains a satchel-only optional attach-offset block, sent only when resending a settled satchel - live throws never have one yet, so their wire format is untouched. - The receiving client's manual bitstream read (mirroring the above) and CClientGame::SendProjectileSync's own write both had to move the satchel case out of the shared GRENADE/TEARGAS/MOLOTOV switch arm to add it. multitheftauto#369 multitheftauto#368
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Sync persistent projectiles (satchels, teargas, molotov) to players who stream in or join after the projectile was created.
Previously, if a satchel charge was thrown while a player was out of range (or not yet connected), no projectile was ever sent to them; it simply didn't exist on their client. This PR introduces three mechanisms to fix that:
ProcessProjectileStreamIn): The server tracks a list of persistent projectiles per-player and periodically sends their creation packet to any nearby player who hasn't been notified yet.PACKET_ID_PROJECTILE_REST_POSITION): Once a satchel settles, the owning client reports its actual resting position and attach offset to the server. Future stream-ins place the satchel directly at that spot instead of replaying the original throw and re-simulating physics (which is non-deterministic).Motivation
Persistent projectiles (satchels in particular) have never been synced to late-joining or streaming-in players. A satchel planted by a player was invisible to anyone not already in range when it was thrown — detonating it would produce an explosion out of thin air on those clients.
Two edge cases drove most of the design:
SetStaticWaitingForCollisionprevents it from falling through the world.Fixes #369 / #368 (duplicated).
Test plan
Satchel visible to late-joining player
Satchel attached to a moving vehicle
Teargas / Molotov visible to streaming-in player
Creator not yet streamed in
Checklist