From b5f6fc578db23ccf5f9a67bf6df3ff7e60fd6294 Mon Sep 17 00:00:00 2001 From: Sardelka Date: Sun, 14 Aug 2022 17:08:43 +0800 Subject: [PATCH] Projectile refactor --- RageCoop.Client/Networking/Receive.cs | 10 +- RageCoop.Client/Networking/Send.cs | 14 +- RageCoop.Client/Sync/Entities/SyncedEntity.cs | 2 +- RageCoop.Client/Sync/Entities/SyncedPed.cs | 7 +- .../Sync/Entities/SyncedProjectile.cs | 121 +++++++++++------- RageCoop.Client/Sync/EntityPool.cs | 22 ++-- RageCoop.Core/CoreUtils.cs | 4 + RageCoop.Core/Packets/Packets.cs | 9 ++ RageCoop.Core/Packets/ProjectileSync.cs | 6 +- 9 files changed, 120 insertions(+), 75 deletions(-) diff --git a/RageCoop.Client/Networking/Receive.cs b/RageCoop.Client/Networking/Receive.cs index 914394a..c8fe10a 100644 --- a/RageCoop.Client/Networking/Receive.cs +++ b/RageCoop.Client/Networking/Receive.cs @@ -416,17 +416,17 @@ namespace RageCoop.Client var p = EntityPool.GetProjectileByID(packet.ID); if (p==null) { - - if (packet.Exploded) { return; } + if (packet.Flags.HasProjDataFlag(ProjectileDataFlags.Exploded)) { return; } // Main.Logger.Debug($"Creating new projectile: {(WeaponHash)packet.WeaponHash}"); EntityPool.ThreadSafe.Add(p=new SyncedProjectile(packet.ID)); } + p.Flags=packet.Flags; p.Position=packet.Position; p.Rotation=packet.Rotation; p.Velocity=packet.Velocity; - p.Hash=(WeaponHash)packet.WeaponHash; - p.ShooterID=packet.ShooterID; - p.Exploded=packet.Exploded; + p.WeaponHash=(WeaponHash)packet.WeaponHash; + p.Shooter= packet.Flags.HasProjDataFlag(ProjectileDataFlags.IsShotByVehicle) ? + (SyncedEntity)EntityPool.GetVehicleByID(packet.ShooterID) : EntityPool.GetPedByID(packet.ShooterID); p.LastSynced=Main.Ticked; } } diff --git a/RageCoop.Client/Networking/Send.cs b/RageCoop.Client/Networking/Send.cs index 112ede2..7fb5e77 100644 --- a/RageCoop.Client/Networking/Send.cs +++ b/RageCoop.Client/Networking/Send.cs @@ -164,17 +164,9 @@ namespace RageCoop.Client } public static void SendProjectile(SyncedProjectile sp) { - var p = sp.MainProjectile; - var packet = SendPackets.ProjectilePacket; - packet.ID =sp.ID; - packet.ShooterID=sp.ShooterID; - packet.Rotation=p.Rotation; - packet.Position=p.Position; - packet.Velocity=p.Velocity; - packet.WeaponHash=(uint)p.WeaponHash; - packet.Exploded=p.IsDead; - if (p.IsDead) { EntityPool.RemoveProjectile(sp.ID, "Dead"); } - SendSync(packet, ConnectionChannel.ProjectileSync); + sp.ExtractData(ref SendPackets.ProjectilePacket); + if (sp.MainProjectile.IsDead) { EntityPool.RemoveProjectile(sp.ID, "Dead"); } + SendSync(SendPackets.ProjectilePacket, ConnectionChannel.ProjectileSync); } diff --git a/RageCoop.Client/Sync/Entities/SyncedEntity.cs b/RageCoop.Client/Sync/Entities/SyncedEntity.cs index 21d19ca..d3ad4bf 100644 --- a/RageCoop.Client/Sync/Entities/SyncedEntity.cs +++ b/RageCoop.Client/Sync/Entities/SyncedEntity.cs @@ -39,7 +39,7 @@ namespace RageCoop.Client } } - internal Player Owner { get; private set; } + internal virtual Player Owner { get; private set; } /// /// /// diff --git a/RageCoop.Client/Sync/Entities/SyncedPed.cs b/RageCoop.Client/Sync/Entities/SyncedPed.cs index e5b34f0..4313fbd 100644 --- a/RageCoop.Client/Sync/Entities/SyncedPed.cs +++ b/RageCoop.Client/Sync/Entities/SyncedPed.cs @@ -667,9 +667,12 @@ namespace RageCoop.Client MainPed.PositionNoOffset=Position; return; } - if (!(localRagdoll || MainPed.IsDead || IsAiming)) + if (!(localRagdoll || MainPed.IsDead)) { - MainPed.Heading=Heading; + if (!IsAiming) + { + MainPed.Heading=Heading; + } MainPed.Velocity=Velocity+5*dist*(Position-MainPed.ReadPosition()); } else if (Main.Ticked-_lastRagdollTime<10) diff --git a/RageCoop.Client/Sync/Entities/SyncedProjectile.cs b/RageCoop.Client/Sync/Entities/SyncedProjectile.cs index 67efb7c..03ac942 100644 --- a/RageCoop.Client/Sync/Entities/SyncedProjectile.cs +++ b/RageCoop.Client/Sync/Entities/SyncedProjectile.cs @@ -1,61 +1,95 @@ using GTA; using GTA.Math; using RageCoop.Core; +using GTA.Native; namespace RageCoop.Client { internal class SyncedProjectile : SyncedEntity { + public ProjectileDataFlags Flags { private get; set; }=ProjectileDataFlags.None; + + public readonly Vector3 Origin; + private bool _firstSend = false; + + + public bool IsValid { get; private set; } = true; + public new bool IsLocal { get; private set; } = false; + public Projectile MainProjectile { get; set; } + public SyncedEntity Shooter { get; set; } + public bool Exploded => Flags.HasProjDataFlag(ProjectileDataFlags.Exploded); + + /// + /// Invalid property for projectile. + /// + private new int OwnerID { set { } } + + internal override Player Owner => Shooter.Owner; + public WeaponHash WeaponHash { get; set; } + private WeaponAsset Asset { get; set; } + public void ExtractData(ref Packets.ProjectileSync p) + { + p.Position=MainProjectile.Position; + p.Velocity=MainProjectile.Velocity; + p.Rotation=MainProjectile.Rotation; + p.ID=ID; + p.ShooterID=Shooter.ID; + p.WeaponHash=(uint)MainProjectile.WeaponHash; + p.Flags=ProjectileDataFlags.None; + if (MainProjectile.IsDead) + { + p.Flags |= ProjectileDataFlags.Exploded; + } + if (MainProjectile.AttachedEntity!=null) + { + p.Flags |= ProjectileDataFlags.IsAttached; + } + if (Shooter is SyncedVehicle) + { + p.Flags |= ProjectileDataFlags.IsShotByVehicle; + } + if (_firstSend) + { + p.Flags |= ProjectileDataFlags.IsAttached; + _firstSend=false; + } + + } public SyncedProjectile(Projectile p) { + var owner = p.OwnerEntity; + if (owner==null) { IsValid=false;return; } ID=EntityPool.RequestNewID(); MainProjectile = p; Origin=p.Position; - var shooter = EntityPool.GetPedByHandle((p.OwnerEntity?.Handle).GetValueOrDefault()); - if (shooter==null) + if(EntityPool.PedsByHandle.TryGetValue(owner.Handle,out var shooter)) { - // Owner will be the vehicle if projectile is shot with a vehicle - var shooterVeh = EntityPool.GetVehicleByHandle((p.OwnerEntity?.Handle).GetValueOrDefault()); - if (shooterVeh!=null && shooterVeh.MainVehicle.Driver!=null) - { - shooter=shooterVeh.MainVehicle.Driver?.GetSyncEntity(); - } - else - { - Main.Logger.Warning($"Could not find owner for projectile:{Hash}"); - } - } - if (shooter != null) - { - if (shooter.MainPed!=null && (p.AttachedEntity==shooter.MainPed.Weapons.CurrentWeaponObject || p.AttachedEntity== shooter.MainPed)) + if (shooter.MainPed!=null + && (p.AttachedEntity==shooter.MainPed.Weapons.CurrentWeaponObject + || p.AttachedEntity== shooter.MainPed)) { // Reloading IsValid=false; + return; } - ShooterID=shooter.ID; + Shooter=shooter; IsLocal=shooter.IsLocal; } - + else if(EntityPool.VehiclesByHandle.TryGetValue(owner.Handle,out var shooterVeh)) + { + Shooter=shooterVeh; + IsLocal=shooterVeh.IsLocal; + } + else + { + IsValid=false; + } } public SyncedProjectile(int id) { ID= id; IsLocal=false; } - public bool IsValid { get; private set; } = true; - public new bool IsLocal { get; private set; } = false; - public bool Exploded { get; set; } = false; - public Projectile MainProjectile { get; set; } - public int ShooterID { get; set; } - private SyncedPed Shooter { get; set; } - public Vector3 Origin { get; set; } - - /// - /// Invalid property for projectile. - /// - private new int OwnerID { set { } } - public WeaponHash Hash { get; set; } - private WeaponAsset Asset { get; set; } internal override void Update() { @@ -74,19 +108,20 @@ namespace RageCoop.Client private void CreateProjectile() { - Asset=new WeaponAsset(Hash); - if (!Asset.IsLoaded) { Asset.Request(); } - World.ShootBullet(Position, Position+Velocity, (Shooter=EntityPool.GetPedByID(ShooterID))?.MainPed, Asset, 0); + Asset=new WeaponAsset(WeaponHash); + if (!Asset.IsLoaded) { Asset.Request(); return; } + if(Shooter == null) { return; } + Entity owner; + owner=(Shooter as SyncedPed)?.MainPed ?? (Entity)(Shooter as SyncedVehicle)?.MainVehicle; + var end = Position+Velocity; + Function.Call(Hash.SHOOT_SINGLE_BULLET_BETWEEN_COORDS_IGNORE_ENTITY, Position.X, Position.Y, Position.Z, end.X, end.Y, end.Z, 0, 1, WeaponHash, owner?.Handle ?? 0, 1, 0, -1,owner); var ps = World.GetAllProjectiles(); MainProjectile=ps[ps.Length-1]; - if (Hash==(WeaponHash)VehicleWeaponHash.Tank) - { - var v = Shooter?.MainPed?.CurrentVehicle; - if (v!=null) - { - World.CreateParticleEffectNonLooped(SyncEvents.CorePFXAsset, "muz_tank", v.Bones[v.GetMuzzleIndex()].Position, v.Bones[35].ForwardVector.ToEulerRotation(v.Bones[35].UpVector), 1); - } - } + MainProjectile.IsCollisionEnabled=false; + MainProjectile.Position=Position; + MainProjectile.Rotation =Rotation; + MainProjectile.Velocity=Velocity; + Main.Delay(()=>MainProjectile.IsCollisionEnabled=true, 100); EntityPool.Add(this); } } diff --git a/RageCoop.Client/Sync/EntityPool.cs b/RageCoop.Client/Sync/EntityPool.cs index ad790b5..b1b45d0 100644 --- a/RageCoop.Client/Sync/EntityPool.cs +++ b/RageCoop.Client/Sync/EntityPool.cs @@ -19,15 +19,15 @@ namespace RageCoop.Client #endif #region ACTIVE INSTANCES - private static Dictionary PedsByID = new Dictionary(); - private static Dictionary PedsByHandle = new Dictionary(); + public static Dictionary PedsByID = new Dictionary(); + public static Dictionary PedsByHandle = new Dictionary(); - private static Dictionary VehiclesByID = new Dictionary(); - private static Dictionary VehiclesByHandle = new Dictionary(); + public static Dictionary VehiclesByID = new Dictionary(); + public static Dictionary VehiclesByHandle = new Dictionary(); - private static Dictionary ProjectilesByID = new Dictionary(); - private static Dictionary ProjectilesByHandle = new Dictionary(); + public static Dictionary ProjectilesByID = new Dictionary(); + public static Dictionary ProjectilesByHandle = new Dictionary(); public static Dictionary ServerProps = new Dictionary(); public static Dictionary ServerBlips = new Dictionary(); @@ -62,7 +62,7 @@ namespace RageCoop.Client foreach (var p in ProjectilesByID.Values) { - if (p.ShooterID!=Main.LocalPlayerID && p.MainProjectile!=null && p.MainProjectile.Exists()) + if (p.Shooter.ID!=Main.LocalPlayerID && p.MainProjectile!=null && p.MainProjectile.Exists()) { p.MainProjectile.Delete(); } @@ -242,6 +242,10 @@ namespace RageCoop.Client public static void Add(SyncedProjectile p) { if (!p.IsValid) { return; } + if (p.WeaponHash==(WeaponHash)VehicleWeaponHash.Tank) + { + Networking.SendBullet(p.Position, p.Position+p.Velocity, (uint)VehicleWeaponHash.Tank, ((SyncedVehicle)p.Shooter).MainVehicle.Driver.GetSyncEntity().ID); + } if (ProjectilesByID.ContainsKey(p.ID)) { ProjectilesByID[p.ID]=p; @@ -339,12 +343,10 @@ namespace RageCoop.Client if (p.MainProjectile.AttachedEntity==null) { // Prevent projectiles from exploding next to vehicle - if (WeaponUtil.VehicleProjectileWeapons.Contains((VehicleWeaponHash)p.MainProjectile.WeaponHash) && - p.MainProjectile.WeaponHash != (WeaponHash)VehicleWeaponHash.Tank && p.Origin.DistanceTo(p.MainProjectile.Position) < 2) + if (p.WeaponHash==(WeaponHash)VehicleWeaponHash.Tank ) { continue; } - Networking.SendProjectile(p); } } diff --git a/RageCoop.Core/CoreUtils.cs b/RageCoop.Core/CoreUtils.cs index c5e6c7a..57b4512 100644 --- a/RageCoop.Core/CoreUtils.cs +++ b/RageCoop.Core/CoreUtils.cs @@ -305,6 +305,10 @@ namespace RageCoop.Core { return (flagToCheck & flag)!=0; } + public static bool HasProjDataFlag(this ProjectileDataFlags flagToCheck, ProjectileDataFlags flag) + { + return (flagToCheck & flag)!=0; + } public static bool HasVehFlag(this VehicleDataFlags flagToCheck, VehicleDataFlags flag) { diff --git a/RageCoop.Core/Packets/Packets.cs b/RageCoop.Core/Packets/Packets.cs index 0e3cf9e..c819c45 100644 --- a/RageCoop.Core/Packets/Packets.cs +++ b/RageCoop.Core/Packets/Packets.cs @@ -97,6 +97,15 @@ namespace RageCoop.Core IsInCover = 1 << 10, IsFullSync = 1<<15 , } + + internal enum ProjectileDataFlags:byte + { + None = 0, + Exploded = 1 << 0, + IsAttached = 1 << 1, + IsOrgin = 1 << 2, + IsShotByVehicle = 1 << 3, + } #region ===== VEHICLE DATA ===== internal enum VehicleDataFlags:ushort { diff --git a/RageCoop.Core/Packets/ProjectileSync.cs b/RageCoop.Core/Packets/ProjectileSync.cs index be918df..5295a72 100644 --- a/RageCoop.Core/Packets/ProjectileSync.cs +++ b/RageCoop.Core/Packets/ProjectileSync.cs @@ -22,7 +22,7 @@ namespace RageCoop.Core public Vector3 Velocity { get; set; } - public bool Exploded { get; set; } + public ProjectileDataFlags Flags { get; set; } @@ -48,7 +48,7 @@ namespace RageCoop.Core // Write velocity byteArray.AddVector3(Velocity); - byteArray.AddBool(Exploded); + byteArray.Add((byte)Flags); return byteArray.ToArray(); @@ -76,7 +76,7 @@ namespace RageCoop.Core // Read velocity Velocity =reader.ReadVector3(); - Exploded=reader.ReadBoolean(); + Flags=(ProjectileDataFlags)reader.ReadByte(); #endregion }