diff --git a/Content.Server/_RMC14/Weapons/Ranged/Prediction/GunPredictionSystem.cs b/Content.Server/_RMC14/Weapons/Ranged/Prediction/GunPredictionSystem.cs index 4374e970bf..105457d741 100644 --- a/Content.Server/_RMC14/Weapons/Ranged/Prediction/GunPredictionSystem.cs +++ b/Content.Server/_RMC14/Weapons/Ranged/Prediction/GunPredictionSystem.cs @@ -102,11 +102,20 @@ private void OnShootRequest(RequestShootEvent ev, EntitySessionEventArgs args) private void OnPredictedMapInit(Entity ent, ref MapInitEvent args) { + if (ent.Comp.Shooter == null) + { + Log.Warning($"{nameof(PredictedProjectileServerComponent)} map initialized with a null shooter session!"); + return; + } + _predicted[(ent.Comp.Shooter.UserId, ent.Comp.ClientId)] = ent; } private void OnPredictedRemove(Entity ent, ref T args) { + if (ent.Comp.Shooter == null) + return; + _predicted.Remove((ent.Comp.Shooter.UserId, ent.Comp.ClientId)); } @@ -173,7 +182,7 @@ private bool Collides( MapCoordinates lowestCoordinate = default; var otherCoordinates = EntityCoordinates.Invalid; - var ping = projectile.Comp1.Shooter.Channel.Ping; + var ping = projectile.Comp1.Shooter?.Channel.Ping ?? 0; // Use 1.5 due to the trip buffer. var sentTime = _timing.CurTime - TimeSpan.FromMilliseconds(ping * 1.5); var pingTime = TimeSpan.FromMilliseconds(ping); @@ -236,7 +245,7 @@ private void ProcessPredictedHit(PredictedProjectileHitEvent ev, ICommonSession return; } - if (predictedProjectile.Shooter.UserId != player.UserId.UserId) + if (predictedProjectile.Shooter?.UserId != player.UserId.UserId) return; if (!_projectileQuery.TryComp(projectile, out var projectileComp) || diff --git a/Content.Shared/Projectiles/SharedProjectileSystem.cs b/Content.Shared/Projectiles/SharedProjectileSystem.cs index 414f8edec8..bd55a8214a 100644 --- a/Content.Shared/Projectiles/SharedProjectileSystem.cs +++ b/Content.Shared/Projectiles/SharedProjectileSystem.cs @@ -101,8 +101,12 @@ public void ProjectileCollide(Entity proj var deleted = Deleted(target); var filter = Filter.Pvs(coordinates, entityMan: EntityManager); - if (_guns.GunPrediction && TryComp(projectile, out PredictedProjectileServerComponent? serverProjectile)) - filter = filter.RemovePlayer(serverProjectile.Shooter); + if (_guns.GunPrediction && + TryComp(projectile, out PredictedProjectileServerComponent? serverProjectile) && + serverProjectile.Shooter is { } shooter) + { + filter = filter.RemovePlayer(shooter); + } if (modifiedDamage is not null && (EntityManager.EntityExists(component.Shooter) || EntityManager.EntityExists(component.Weapon))) { diff --git a/Content.Shared/_RMC14/Weapons/Ranged/Prediction/PredictedProjectileServerComponent.cs b/Content.Shared/_RMC14/Weapons/Ranged/Prediction/PredictedProjectileServerComponent.cs index be1f69b08d..bc2d1b4f51 100644 --- a/Content.Shared/_RMC14/Weapons/Ranged/Prediction/PredictedProjectileServerComponent.cs +++ b/Content.Shared/_RMC14/Weapons/Ranged/Prediction/PredictedProjectileServerComponent.cs @@ -7,7 +7,7 @@ namespace Content.Shared._RMC14.Weapons.Ranged.Prediction; [RegisterComponent, NetworkedComponent, AutoGenerateComponentState] public sealed partial class PredictedProjectileServerComponent : Component { - public ICommonSession Shooter; + public ICommonSession? Shooter; [DataField, AutoNetworkedField] public int ClientId;