diff --git a/Client/COOPAPI.cs b/Client/COOPAPI.cs index 3dac450..6769f49 100644 --- a/Client/COOPAPI.cs +++ b/Client/COOPAPI.cs @@ -243,7 +243,7 @@ namespace RageCoop.Client /// true to disable traffic public static void SetLocalTraffic(bool enable) { - Main.DisableTraffic = !enable; + Main.Settings.DisableTraffic = !enable; } /// diff --git a/Client/Main.cs b/Client/Main.cs index b568b2c..9cc0ec0 100644 --- a/Client/Main.cs +++ b/Client/Main.cs @@ -26,7 +26,6 @@ namespace RageCoop.Client public static readonly string CurrentVersion = "V0_1"; public static int LocalPlayerID=0; - public static bool DisableTraffic = true; public static bool NPCsAllowed = false; internal static RelationshipGroup SyncedPedsGroup; diff --git a/Client/Menus/RageCoopMenu.cs b/Client/Menus/RageCoopMenu.cs index b3541c9..30902bb 100644 --- a/Client/Menus/RageCoopMenu.cs +++ b/Client/Menus/RageCoopMenu.cs @@ -97,7 +97,7 @@ namespace RageCoop.Client.Menus { MainMenu.Items[2].Enabled = true; MainMenu.Items[2].Title = "Disconnect"; - SubSettings.MainMenu.Items[1].Enabled = !Main.DisableTraffic && Main.NPCsAllowed; + SubSettings.MainMenu.Items[1].Enabled = !Main.Settings.DisableTraffic && Main.NPCsAllowed; MainMenu.Visible = false; } diff --git a/Client/Menus/Sub/SettingsMenu.cs b/Client/Menus/Sub/SettingsMenu.cs index 45fc1c5..44eac15 100644 --- a/Client/Menus/Sub/SettingsMenu.cs +++ b/Client/Menus/Sub/SettingsMenu.cs @@ -17,7 +17,7 @@ namespace RageCoop.Client.Menus.Sub Alignment = Main.Settings.FlipMenu ? GTA.UI.Alignment.Right : GTA.UI.Alignment.Left }; - private readonly NativeCheckboxItem _disableTrafficItem = new NativeCheckboxItem("Disable Traffic (NPCs/Vehicles)", "Local traffic only", Main.DisableTraffic); + private readonly NativeCheckboxItem _disableTrafficItem = new NativeCheckboxItem("Disable Traffic (NPCs/Vehicles)", "Local traffic only", Main.Settings.DisableTraffic); private readonly NativeCheckboxItem _flipMenuItem = new NativeCheckboxItem("Flip menu", Main.Settings.FlipMenu); private readonly NativeCheckboxItem _showNetworkInfoItem = new NativeCheckboxItem("Show Network Info", Networking.ShowNetworkInfo); private static NativeItem _menuKey = new NativeItem("Menu Key","The key to open menu", Main.Settings.MenuKey.ToString()); @@ -74,7 +74,7 @@ namespace RageCoop.Client.Menus.Sub public void DisableTrafficCheckboxChanged(object a, System.EventArgs b) { - Main.DisableTraffic = _disableTrafficItem.Checked; + Main.Settings.DisableTraffic = _disableTrafficItem.Checked; } public void FlipMenuCheckboxChanged(object a, System.EventArgs b) diff --git a/Client/Misc/Util.cs b/Client/Misc/Util.cs index cf0fb63..2e2a7f0 100644 --- a/Client/Misc/Util.cs +++ b/Client/Misc/Util.cs @@ -60,7 +60,7 @@ namespace RageCoop.Client { XmlSerializer ser = new XmlSerializer(typeof(Settings)); - string path = Directory.GetCurrentDirectory() + "\\Scripts\\RageCoop\\Settings.xml"; + string path = Directory.GetCurrentDirectory() + "\\Scripts\\RageCoop\\RageCoop.Client.Settings.xml"; Settings settings = null; if (File.Exists(path)) @@ -89,7 +89,7 @@ namespace RageCoop.Client { try { - string path = Directory.GetCurrentDirectory() + "\\Scripts\\RageCoop\\Settings.xml"; + string path = Directory.GetCurrentDirectory() + "\\Scripts\\RageCoop\\RageCoop.Client.Settings.xml"; using (FileStream stream = new FileStream(path, File.Exists(path) ? FileMode.Truncate : FileMode.Create, FileAccess.ReadWrite)) { @@ -487,6 +487,12 @@ namespace RageCoop.Client return p.Bones[Bone.SkelRightHand].Position; } + public static bool IsUsingProjectileWeapon(this Ped p) + { + var w = p.Weapons.Current; + return w.Group==WeaponGroup.Thrown||ProjectileWeapons.Contains(w.Hash); + } + #endregion #region VEHICLE @@ -890,7 +896,33 @@ namespace RageCoop.Client {WeaponHash.PumpShotgunMk2,7}, }; - + public static readonly HashSet ProjectileWeapons = new HashSet { + WeaponHash.HomingLauncher, + WeaponHash.RPG, + WeaponHash.Firework, + WeaponHash.UpNAtomizer, + WeaponHash.GrenadeLauncher, + WeaponHash.GrenadeLauncherSmoke, + WeaponHash.CompactGrenadeLauncher + }; + /* + public static readonly Dictionary WeaponExplosionTypes = new Dictionary { + { WeaponHash.Grenade,ExplosionType.Grenade}, + { WeaponHash.GrenadeLauncher,ExplosionType.Grenade}, + { WeaponHash.CompactGrenadeLauncher,ExplosionType.Grenade}, + { WeaponHash.SmokeGrenade,ExplosionType.SmokeG}, + { WeaponHash.GrenadeLauncherSmoke,ExplosionType.SmokeG}, + { WeaponHash.StickyBomb,ExplosionType.StickyBomb}, + { WeaponHash.Flare,ExplosionType.Flare}, + { WeaponHash.FlareGun,ExplosionType.Flare}, + { WeaponHash.Molotov,ExplosionType.Molotov1}, + { WeaponHash.BZGas,ExplosionType.BZGas}, + { WeaponHash.PipeBomb,ExplosionType.PipeBomb}, + { WeaponHash.ProximityMine,ExplosionType.ProxMine}, + { WeaponHash.Firework,ExplosionType.FireWork}, + { WeaponHash.RPG,ExplosionType.Rocket}, + }; + */ } /// /// diff --git a/Client/Networking/Networking.cs b/Client/Networking/Networking.cs index 5f32a05..2b3f53f 100644 --- a/Client/Networking/Networking.cs +++ b/Client/Networking/Networking.cs @@ -11,7 +11,7 @@ using GTA.Native; namespace RageCoop.Client { - public static partial class Networking + internal static partial class Networking { public static NetClient Client; public static float Latency = 0; diff --git a/Client/Networking/Receive.cs b/Client/Networking/Receive.cs index d25db7a..d66d053 100644 --- a/Client/Networking/Receive.cs +++ b/Client/Networking/Receive.cs @@ -10,7 +10,7 @@ using GTA.Native; namespace RageCoop.Client { - public static partial class Networking + internal static partial class Networking { public static void ReceiveMessages() { @@ -137,6 +137,13 @@ namespace RageCoop.Client } break; + case PacketTypes.PlayerInfoUpdate: + { + var packet = new Packets.PlayerInfoUpdate(); + packet.Unpack(data); + PlayerList.SetPlayer(packet.PedID,packet.Username,packet.Latency); + break; + } #region ENTITY SYNC case PacketTypes.VehicleSync: { @@ -147,7 +154,7 @@ namespace RageCoop.Client } break; - case PacketTypes.CharacterSync: + case PacketTypes.PedSync: { Packets.PedSync packet = new Packets.PedSync(); @@ -165,7 +172,7 @@ namespace RageCoop.Client } break; - case PacketTypes.CharacterStateSync: + case PacketTypes.PedStateSync: { @@ -175,6 +182,13 @@ namespace RageCoop.Client } break; + case PacketTypes.ProjectileSync: + { + Packets.ProjectileSync packet = new Packets.ProjectileSync(); + packet.Unpack(data); + ProjectileSync(packet); + break; + } #endregion case PacketTypes.ChatMessage: { @@ -289,125 +303,132 @@ namespace RageCoop.Client Client.Recycle(message); } } + + private static void PedSync(Packets.PedSync packet) { - lock (EntityPool.PedsLock) + if (!EntityPool.PedExists(packet.ID)) { - if (!EntityPool.Exists(packet.ID)) - { - Main.Logger.Debug($"Creating character for incoming sync:{packet.ID}"); - - EntityPool.Add(new SyncedPed(packet.ID)); - } - PedDataFlags flags=packet.Flag; - SyncedPed c = EntityPool.GetPedByID(packet.ID); - c.ID=packet.ID; - //c.OwnerID=packet.OwnerID; - c.Health = packet.Health; - c.Position = packet.Position.ToVector(); - c.Rotation = packet.Rotation.ToVector(); - c.Velocity = packet.Velocity.ToVector(); - c.Speed = packet.Speed; - c.CurrentWeaponHash = packet.CurrentWeaponHash; - c.IsAiming = flags.HasFlag(PedDataFlags.IsAiming); - c.IsReloading = flags.HasFlag(PedDataFlags.IsReloading); - c.IsJumping = flags.HasFlag(PedDataFlags.IsJumping) ; - c.IsRagdoll = flags.HasFlag(PedDataFlags.IsRagdoll); - c.IsOnFire = flags.HasFlag(PedDataFlags.IsOnFire) ; - c.IsInParachuteFreeFall = flags.HasFlag(PedDataFlags.IsInParachuteFreeFall); - c.IsParachuteOpen = flags.HasFlag(PedDataFlags.IsParachuteOpen); - c.IsOnLadder = flags.HasFlag(PedDataFlags.IsOnLadder); - c.IsVaulting = flags.HasFlag(PedDataFlags.IsVaulting); - c.IsInCover = flags.HasFlag(PedDataFlags.IsInCover); - c.Heading=packet.Heading; - c.LastSynced = Main.Ticked; - if (c.IsAiming) - { - c.AimCoords = packet.AimCoords.ToVector(); - } - if (c.IsRagdoll) - { - c.RotationVelocity=packet.RotationVelocity.ToVector(); - } + Main.Logger.Debug($"Creating character for incoming sync:{packet.ID}"); + + EntityPool.ThreadSafe.Add(new SyncedPed(packet.ID)); + } + PedDataFlags flags = packet.Flag; + SyncedPed c = EntityPool.GetPedByID(packet.ID); + c.ID=packet.ID; + //c.OwnerID=packet.OwnerID; + c.Health = packet.Health; + c.Position = packet.Position.ToVector(); + c.Rotation = packet.Rotation.ToVector(); + c.Velocity = packet.Velocity.ToVector(); + c.Speed = packet.Speed; + c.CurrentWeaponHash = packet.CurrentWeaponHash; + c.IsAiming = flags.HasFlag(PedDataFlags.IsAiming); + c.IsReloading = flags.HasFlag(PedDataFlags.IsReloading); + c.IsJumping = flags.HasFlag(PedDataFlags.IsJumping); + c.IsRagdoll = flags.HasFlag(PedDataFlags.IsRagdoll); + c.IsOnFire = flags.HasFlag(PedDataFlags.IsOnFire); + c.IsInParachuteFreeFall = flags.HasFlag(PedDataFlags.IsInParachuteFreeFall); + c.IsParachuteOpen = flags.HasFlag(PedDataFlags.IsParachuteOpen); + c.IsOnLadder = flags.HasFlag(PedDataFlags.IsOnLadder); + c.IsVaulting = flags.HasFlag(PedDataFlags.IsVaulting); + c.IsInCover = flags.HasFlag(PedDataFlags.IsInCover); + c.Heading=packet.Heading; + c.LastSynced = Main.Ticked; + if (c.IsAiming) + { + c.AimCoords = packet.AimCoords.ToVector(); + } + if (c.IsRagdoll) + { + c.RotationVelocity=packet.RotationVelocity.ToVector(); } } private static void PedStateSync(Packets.PedStateSync packet) { - lock (EntityPool.PedsLock) + if (!EntityPool.PedExists(packet.ID)) { - if (!EntityPool.Exists(packet.ID)) - { - Main.Logger.Debug($"Creating character for incoming sync:{packet.ID}"); + Main.Logger.Debug($"Creating character for incoming sync:{packet.ID}"); - EntityPool.Add(new SyncedPed(packet.ID)); - } - SyncedPed c = EntityPool.GetPedByID(packet.ID); - c.ID=packet.ID; - c.OwnerID=packet.OwnerID; - c.Clothes=packet.Clothes; - c.WeaponComponents=packet.WeaponComponents; - c.ModelHash=packet.ModelHash; - c.LastSynced=c.LastStateSynced = Main.Ticked; + EntityPool.ThreadSafe.Add(new SyncedPed(packet.ID)); } + SyncedPed c = EntityPool.GetPedByID(packet.ID); + c.ID=packet.ID; + c.OwnerID=packet.OwnerID; + c.Clothes=packet.Clothes; + c.WeaponComponents=packet.WeaponComponents; + c.ModelHash=packet.ModelHash; + c.LastSynced=c.LastStateSynced = Main.Ticked; } private static void VehicleSync(Packets.VehicleSync packet) { - lock (EntityPool.VehiclesLock) + if (!EntityPool.VehicleExists(packet.ID)) { - if (!EntityPool.Exists(packet.ID)) - { - EntityPool.Add(new SyncedVehicle(packet.ID)); - } - SyncedVehicle v = EntityPool.GetVehicleByID(packet.ID); - v.ID= packet.ID; - v.Position=packet.Position.ToVector(); - v.Rotation=packet.Rotation.ToVector(); - v.SteeringAngle=packet.SteeringAngle; - v.ThrottlePower=packet.ThrottlePower; - v.BrakePower=packet.BrakePower; - v.Velocity=packet.Velocity.ToVector(); - v.RotationVelocity=packet.RotationVelocity.ToVector(); - v.LastSynced=Main.Ticked; + EntityPool.ThreadSafe.Add(new SyncedVehicle(packet.ID)); } + SyncedVehicle v = EntityPool.GetVehicleByID(packet.ID); + v.ID= packet.ID; + v.Position=packet.Position.ToVector(); + v.Rotation=packet.Rotation.ToVector(); + v.SteeringAngle=packet.SteeringAngle; + v.ThrottlePower=packet.ThrottlePower; + v.BrakePower=packet.BrakePower; + v.Velocity=packet.Velocity.ToVector(); + v.RotationVelocity=packet.RotationVelocity.ToVector(); + v.LastSynced=Main.Ticked; } private static void VehicleStateSync(Packets.VehicleStateSync packet) { - lock (EntityPool.VehiclesLock) + if (!EntityPool.VehicleExists(packet.ID)) { - if (!EntityPool.Exists(packet.ID)) - { - EntityPool.Add( new SyncedVehicle(packet.ID)); - } - SyncedVehicle v = EntityPool.GetVehicleByID(packet.ID); - v.ID= packet.ID; - v.OwnerID= packet.OwnerID; - v.DamageModel=packet.DamageModel; - v.EngineHealth=packet.EngineHealth; - v.OwnerID=packet.OwnerID; - v.Mods=packet.Mods; - v.ModelHash=packet.ModelHash; - v.Colors=packet.Colors; - v.LandingGear=packet.LandingGear; - v.EngineRunning = packet.Flag.HasFlag(VehicleDataFlags.IsEngineRunning); - v.LightsOn = packet.Flag.HasFlag(VehicleDataFlags.AreLightsOn); - v.BrakeLightsOn = packet.Flag.HasFlag(VehicleDataFlags.AreBrakeLightsOn); - v.HighBeamsOn = packet.Flag.HasFlag(VehicleDataFlags.AreHighBeamsOn); - v.SireneActive = packet.Flag.HasFlag(VehicleDataFlags.IsSirenActive) ; - v.IsDead = packet.Flag.HasFlag(VehicleDataFlags.IsDead) ; - v.HornActive = packet.Flag.HasFlag(VehicleDataFlags.IsHornActive); - v.Transformed = packet.Flag.HasFlag(VehicleDataFlags.IsTransformed); - v.Passengers=new Dictionary(); - v.LockStatus=packet.LockStatus; - foreach (KeyValuePair pair in packet.Passengers) - { - if (EntityPool.Exists(pair.Value)) - { - v.Passengers.Add((VehicleSeat)pair.Key, EntityPool.GetPedByID(pair.Value)); - } - } - v.LastStateSynced=v.LastSynced= Main.Ticked; + EntityPool.ThreadSafe.Add(new SyncedVehicle(packet.ID)); } + SyncedVehicle v = EntityPool.GetVehicleByID(packet.ID); + v.ID= packet.ID; + v.OwnerID= packet.OwnerID; + v.DamageModel=packet.DamageModel; + v.EngineHealth=packet.EngineHealth; + v.OwnerID=packet.OwnerID; + v.Mods=packet.Mods; + v.ModelHash=packet.ModelHash; + v.Colors=packet.Colors; + v.LandingGear=packet.LandingGear; + v.EngineRunning = packet.Flag.HasFlag(VehicleDataFlags.IsEngineRunning); + v.LightsOn = packet.Flag.HasFlag(VehicleDataFlags.AreLightsOn); + v.BrakeLightsOn = packet.Flag.HasFlag(VehicleDataFlags.AreBrakeLightsOn); + v.HighBeamsOn = packet.Flag.HasFlag(VehicleDataFlags.AreHighBeamsOn); + v.SireneActive = packet.Flag.HasFlag(VehicleDataFlags.IsSirenActive); + v.IsDead = packet.Flag.HasFlag(VehicleDataFlags.IsDead); + v.HornActive = packet.Flag.HasFlag(VehicleDataFlags.IsHornActive); + v.Transformed = packet.Flag.HasFlag(VehicleDataFlags.IsTransformed); + v.Passengers=new Dictionary(); + v.LockStatus=packet.LockStatus; + foreach (KeyValuePair pair in packet.Passengers) + { + if (EntityPool.PedExists(pair.Value)) + { + v.Passengers.Add((VehicleSeat)pair.Key, EntityPool.GetPedByID(pair.Value)); + } + } + v.LastStateSynced=v.LastSynced= Main.Ticked; + + } + private static void ProjectileSync(Packets.ProjectileSync packet) + { + var p = EntityPool.GetProjectileByID(packet.ID); + if (p==null) + { + if (packet.Exploded) { return; } + Main.Logger.Debug($"Creating new projectile: {(WeaponHash)packet.WeaponHash}"); + EntityPool.ThreadSafe.Add(p=new SyncedProjectile(packet.ID)); + } + p.Position=packet.Position.ToVector(); + p.Rotation=packet.Rotation.ToVector(); + p.Velocity=packet.Velocity.ToVector(); + p.Hash=(WeaponHash)packet.WeaponHash; + p.ShooterID=packet.ShooterID; + p.Exploded=packet.Exploded; + p.LastSynced=Main.Ticked; } - } } diff --git a/Client/Networking/Send.cs b/Client/Networking/Send.cs index 90e7487..bd8ec41 100644 --- a/Client/Networking/Send.cs +++ b/Client/Networking/Send.cs @@ -11,23 +11,24 @@ using GTA.Math; namespace RageCoop.Client { - public static partial class Networking + internal static partial class Networking { + + #region -- SEND -- /// /// Pack the packet then send to server. /// /// /// /// - public static void Send(Packet p, ConnectionChannel channel = ConnectionChannel.Default,NetDeliveryMethod method=NetDeliveryMethod.UnreliableSequenced) + public static void Send(Packet p, ConnectionChannel channel = ConnectionChannel.Default, NetDeliveryMethod method = NetDeliveryMethod.UnreliableSequenced) { NetOutgoingMessage outgoingMessage = Client.CreateMessage(); p.Pack(outgoingMessage); Client.SendMessage(outgoingMessage, method, (int)channel); } - #region -- SEND -- public static void SendPed(SyncedPed c) { Ped p = c.MainPed; @@ -51,7 +52,7 @@ namespace RageCoop.Client { packet.RotationVelocity=p.RotationVelocity.ToLVector(); } - Send(packet, ConnectionChannel.CharacterSync); + Send(packet, ConnectionChannel.PedSync); } public static void SendPedState(SyncedPed c) { @@ -66,7 +67,7 @@ namespace RageCoop.Client WeaponComponents=p.Weapons.Current.GetWeaponComponents(), }; - Send(packet, ConnectionChannel.CharacterSync); + Send(packet, ConnectionChannel.PedSync); } public static void SendVehicle(SyncedVehicle v) { @@ -109,6 +110,23 @@ namespace RageCoop.Client }; Send(packet, ConnectionChannel.VehicleSync); } + public static void SendProjectile(SyncedProjectile sp) + { + var p = sp.MainProjectile; + var packet = new Packets.ProjectileSync() + { + ID =sp.ID, + ShooterID=sp.ShooterID, + Position=p.Position.ToLVector(), + Rotation=p.Rotation.ToLVector(), + Velocity=p.Velocity.ToLVector(), + WeaponHash=(uint)p.WeaponHash, + Exploded=p.IsDead + }; + if (p.IsDead) { EntityPool.RemoveProjectile(sp.ID,"Dead"); } + Send(packet, ConnectionChannel.ProjectileSync); + } + #region SYNC EVENTS public static void SendBulletShot(Vector3 start,Vector3 end,uint weapon,int ownerID) diff --git a/Client/PlayerList.cs b/Client/PlayerList.cs index 361de7e..9cd47dc 100644 --- a/Client/PlayerList.cs +++ b/Client/PlayerList.cs @@ -58,7 +58,7 @@ namespace RageCoop.Client _mainScaleform.CallFunction("SET_TITLE", "Player list", (Players.Count) + " players"); _mainScaleform.CallFunction("DISPLAY_VIEW"); } - public static void SetPlayer(int id, string username) + public static void SetPlayer(int id, string username,float latency=0) { var toset = Players.Where(x => x.PedID==id); @@ -67,10 +67,11 @@ namespace RageCoop.Client var p=toset.First(); p.Username=username; p.PedID=id; + p.Latency=latency; } else { - PlayerData p = new PlayerData { PedID=id, Username=username }; + PlayerData p = new PlayerData { PedID=id, Username=username,Latency=latency }; Players.Add(p); } } diff --git a/Client/Settings.cs b/Client/Settings.cs index 7160c2a..a39b4e9 100644 --- a/Client/Settings.cs +++ b/Client/Settings.cs @@ -40,5 +40,11 @@ namespace RageCoop.Client /// public Keys PassengerKey { get; set; }=Keys.G; + /// + /// Disable world NPC traffic, mission entities won't be affected + /// + public bool DisableTraffic { get; set; } = true; + + } } diff --git a/Client/Sync/Entities/SyncedPed.cs b/Client/Sync/Entities/SyncedPed.cs index fca96ac..edd174c 100644 --- a/Client/Sync/Entities/SyncedPed.cs +++ b/Client/Sync/Entities/SyncedPed.cs @@ -24,15 +24,7 @@ namespace RageCoop.Client /// public SyncedPed(Ped p) { - while((ID==0) || (EntityPool.GetPedByID(ID)!=null)) - { - byte[] rngBytes = new byte[4]; - - RandomNumberGenerator.Create().GetBytes(rngBytes); - - // Convert the bytes into an integer - ID = BitConverter.ToInt32(rngBytes,0); - } + ID=EntityPool.RequestNewID(); p.CanWrithe=false; p.IsOnlyDamagedByPlayer=false; MainPed=p; @@ -143,7 +135,8 @@ namespace RageCoop.Client { SetClothes(); } - + + CheckCurrentWeapon(); } @@ -500,7 +493,6 @@ namespace RageCoop.Client } } - CheckCurrentWeapon(); if (IsReloading) { @@ -576,27 +568,25 @@ namespace RageCoop.Client if (MainPed.Weapons.Current.Hash != (WeaponHash)CurrentWeaponHash || !WeaponComponents.Compare(_lastWeaponComponents)) { MainPed.Weapons.RemoveAll(); - + _lastWeaponObj = Function.Call(Hash.CREATE_WEAPON_OBJECT, CurrentWeaponHash, -1, Position.X, Position.Y, Position.Z, true, 0, 0); + if (CurrentWeaponHash != (uint)WeaponHash.Unarmed) { - if (WeaponComponents == null || WeaponComponents.Count == 0) + if (WeaponComponents != null && WeaponComponents.Count != 0) { - MainPed.Weapons.Give((WeaponHash)CurrentWeaponHash, 0, true, true); - } - else - { - _lastWeaponObj = Function.Call(Hash.CREATE_WEAPON_OBJECT, CurrentWeaponHash, -1, Position.X, Position.Y, Position.Z, true, 0, 0); - foreach (KeyValuePair comp in WeaponComponents) { + if (comp.Value) { Function.Call(Hash.GIVE_WEAPON_COMPONENT_TO_WEAPON_OBJECT, _lastWeaponObj, comp.Key); } + } - Function.Call(Hash.GIVE_WEAPON_OBJECT_TO_PED, _lastWeaponObj, MainPed.Handle); } + Function.Call(Hash.GIVE_WEAPON_OBJECT_TO_PED, _lastWeaponObj, MainPed.Handle); + } _lastWeaponComponents = WeaponComponents; diff --git a/Client/Sync/Entities/SyncedProjectile.cs b/Client/Sync/Entities/SyncedProjectile.cs index e4f77a5..8ae35e3 100644 --- a/Client/Sync/Entities/SyncedProjectile.cs +++ b/Client/Sync/Entities/SyncedProjectile.cs @@ -7,74 +7,56 @@ using GTA; namespace RageCoop.Client { - internal class SyncedProjectile:SyncedEntity + internal class SyncedProjectile : SyncedEntity { + public SyncedProjectile(Projectile p) + { + ID=EntityPool.RequestNewID(); + IsMine=true; + MainProjectile = p; + ShooterID=p.Owner.GetSyncEntity().ID; + } + public SyncedProjectile(int id) + { + ID= id; + IsMine=false; + } + public new bool IsMine { get; private set; } public bool Exploded { get; set; } = false; public Projectile MainProjectile { get; set; } public int ShooterID { get; set; } + + /// + /// Invalid property for projectile. + /// + private new int OwnerID{ set { } } public WeaponHash Hash { get; set; } private WeaponAsset Asset { get; set; } - private bool _creatingProjectile{ get;set; }=false; - private ulong _projectileShotTime { get;set; } public override void Update() { - // Check if all data avalible - if (!IsReady) { return; } // Skip update if no new sync message has arrived. - if (!NeedUpdate) - { return; } - - if (_creatingProjectile) { return; } + if (!NeedUpdate){ return; } if (MainProjectile == null || !MainProjectile.Exists()) { CreateProjectile(); return; } - MainProjectile.Position=Position+Velocity*Networking.Latency; + MainProjectile.PositionNoOffset=Position+Velocity*Networking.Latency; MainProjectile.Velocity=Velocity; MainProjectile.Rotation=Rotation; - if (Exploded) - { - if (Exploded) - { - if(MainProjectile != null && MainProjectile.Exists()) - { - MainProjectile.Explode(); - return; - } - } - } + LastUpdated=Main.Ticked; } private void CreateProjectile() { Asset=new WeaponAsset(Hash); if (!Asset.IsLoaded) { Asset.Request(); } - World.ShootBullet(Position,Position+Velocity,EntityPool.GetPedByID(ShooterID)?.MainPed,Asset,0,Velocity.Length()); - _projectileShotTime=Main.Ticked; - _creatingProjectile=true; - - EventHandler checker = null; - checker= (sender, e) => - { - if (Main.Ticked<=_projectileShotTime+1) - { - if (e.Projectile.WeaponHash==Hash) - { - MainProjectile=e.Projectile; - _creatingProjectile=false; - SyncEvents.OnProjectileShot-=checker; - } - } - else - { - _creatingProjectile=false; - SyncEvents.OnProjectileShot-=checker; - } - }; - SyncEvents.OnProjectileShot+=checker; + World.ShootBullet(Position,Position+Velocity,EntityPool.GetPedByID(ShooterID)?.MainPed,Asset,0); + var ps = World.GetAllProjectiles(); + MainProjectile=ps[ps.Length-1]; + EntityPool.Add(this); } } } diff --git a/Client/Sync/Entities/SyncedVehicle.cs b/Client/Sync/Entities/SyncedVehicle.cs index fecceb8..bb112be 100644 --- a/Client/Sync/Entities/SyncedVehicle.cs +++ b/Client/Sync/Entities/SyncedVehicle.cs @@ -22,15 +22,8 @@ namespace RageCoop.Client /// public SyncedVehicle(Vehicle v) { - while ((ID==0) || EntityPool.Exists(ID)) - { - byte[] rngBytes = new byte[4]; - RandomNumberGenerator.Create().GetBytes(rngBytes); - - // Convert the bytes into an integer - ID = BitConverter.ToInt32(rngBytes, 0); - } + ID=EntityPool.RequestNewID(); MainVehicle=v; MainVehicle.CanPretendOccupants=false; OwnerID=Main.LocalPlayerID; diff --git a/Client/Sync/EntityPool.cs b/Client/Sync/EntityPool.cs index 974810d..d5936b0 100644 --- a/Client/Sync/EntityPool.cs +++ b/Client/Sync/EntityPool.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Text; using System.Diagnostics; using System.Threading.Tasks; +using System.Security.Cryptography; namespace RageCoop.Client { @@ -26,6 +27,11 @@ namespace RageCoop.Client private static Dictionary ID_Vehicles = new Dictionary(); private static Dictionary Handle_Vehicles = new Dictionary(); + public static object ProjectilesLock = new object(); + private static Dictionary ID_Projectiles = new Dictionary(); + private static Dictionary Handle_Projectiles = new Dictionary(); + + public static void Cleanup(bool keepPlayer=true,bool keepMine=true) { foreach(int id in new List(ID_Peds.Keys)) @@ -44,6 +50,9 @@ namespace RageCoop.Client } ID_Vehicles.Clear(); Handle_Vehicles.Clear(); + + ID_Projectiles.Clear(); + Handle_Projectiles.Clear(); } public static SyncedPed GetPedByID(int id) { @@ -193,22 +202,111 @@ namespace RageCoop.Client } - - public static bool Exists(int id) + public static SyncedProjectile GetProjectileByID(int id) { - return ID_Peds.ContainsKey(id) || ID_Vehicles.ContainsKey(id); + return ID_Projectiles.ContainsKey(id) ? ID_Projectiles[id] : null; + } + public static void Add(SyncedProjectile p) + { + if (ID_Projectiles.ContainsKey(p.ID)) + { + ID_Projectiles[p.ID]=p; + } + else + { + ID_Projectiles.Add(p.ID, p); + } + if (p.MainProjectile==null) { return; } + if (Handle_Projectiles.ContainsKey(p.MainProjectile.Handle)) + { + Handle_Projectiles[p.MainProjectile.Handle]=p; + } + else + { + Handle_Projectiles.Add(p.MainProjectile.Handle, p); + } + } + public static void RemoveProjectile(int id, string reason) + { + if (ID_Projectiles.ContainsKey(id)) + { + SyncedProjectile sp = ID_Projectiles[id]; + var p = sp.MainProjectile; + if (p!=null) + { + if (Handle_Projectiles.ContainsKey(p.Handle)) + { + Handle_Projectiles.Remove(p.Handle); + } + Main.Logger.Debug($"Removing projectile {sp.ID}. Reason:{reason}"); + p.Explode(); + } + ID_Projectiles.Remove(id); + } + } + + public static bool PedExists(int id) + { + return ID_Peds.ContainsKey(id); + } + public static bool VehicleExists(int id) + { + return ID_Vehicles.ContainsKey(id); + } + public static bool ProjectileExists(int id) + { + return ID_Projectiles.ContainsKey(id); } public static void DoSync() { PerfCounter.Restart(); - SyncEvents.CheckProjectiles(); Debug.TimeStamps[TimeStamp.CheckProjectiles]=PerfCounter.ElapsedTicks; var allPeds = World.GetAllPeds(); var allVehicles=World.GetAllVehicles(); + var allProjectiles=World.GetAllProjectiles(); + if (Main.Ticked%100==0) { if (allVehicles.Length>50) { SetBudget(0); } else { SetBudget(1); } } Debug.TimeStamps[TimeStamp.GetAllEntities]=PerfCounter.ElapsedTicks; + lock (ProjectilesLock) + { - lock (EntityPool.PedsLock) + foreach (Projectile p in allProjectiles) + { + if (!Handle_Projectiles.ContainsKey(p.Handle)) + { + Add(new SyncedProjectile(p)); + Main.Logger.Debug($"Projectile shot: {p.Handle}"); + } + } + + foreach (SyncedProjectile p in ID_Projectiles.Values.ToArray()) + { + + // Outgoing sync + if (p.IsMine) + { + if (p.MainProjectile.AttachedEntity==null) + { + Networking.SendProjectile(p); + } + } + else // Incoming sync + { + if (p.Exploded || p.IsOutOfSync) + { + RemoveProjectile(p.ID, "OutOfSync | Exploded"); + } + else + { + p.Update(); + } + + } + + } + + } + lock (PedsLock) { EntityPool.AddPlayer(); @@ -255,16 +353,10 @@ namespace RageCoop.Client } else // Incoming sync { - - c.Update(); if (c.IsOutOfSync) { - try - { - EntityPool.RemovePed(c.ID,"OutOfSync"); - } - catch { } + RemovePed(c.ID, "OutOfSync"); } } @@ -272,13 +364,12 @@ namespace RageCoop.Client Debug.TimeStamps[TimeStamp.PedTotal]=PerfCounter.ElapsedTicks; } - lock (EntityPool.VehiclesLock) + lock (VehiclesLock) { foreach (Vehicle veh in allVehicles) { - SyncedVehicle v = EntityPool.GetVehicleByHandle(veh.Handle); - if (v==null) + if (!Handle_Vehicles.ContainsKey(veh.Handle)) { Main.Logger.Debug($"Creating SyncEntity for vehicle, handle:{veh.Handle}"); @@ -318,11 +409,7 @@ namespace RageCoop.Client v.Update(); if (v.IsOutOfSync) { - try - { - EntityPool.RemoveVehicle(v.ID, "OutOfSync"); - } - catch { } + RemoveVehicle(v.ID, "OutOfSync"); } } @@ -335,6 +422,8 @@ namespace RageCoop.Client } + + public static void RemoveAllFromPlayer(int playerPedId) { foreach(SyncedPed p in ID_Peds.Values.ToArray()) @@ -352,6 +441,24 @@ namespace RageCoop.Client } } } + + public static int RequestNewID() + { + int ID=0; + while ((ID==0) + || ID_Peds.ContainsKey(ID) + || ID_Vehicles.ContainsKey(ID) + || ID_Projectiles.ContainsKey(ID)) + { + byte[] rngBytes = new byte[4]; + + RandomNumberGenerator.Create().GetBytes(rngBytes); + + // Convert the bytes into an integer + ID = BitConverter.ToInt32(rngBytes, 0); + } + return ID; + } private static void SetBudget(int b) { Function.Call(Hash.SET_PED_POPULATION_BUDGET, b); // 0 - 3 @@ -366,5 +473,29 @@ namespace RageCoop.Client s+="\nHandle_Vehicles: "+Handle_Vehicles.Count; return s; } + public static class ThreadSafe + { + public static void Add(SyncedVehicle v) + { + lock (EntityPool.VehiclesLock) + { + EntityPool.Add(v); + } + } + public static void Add(SyncedPed p) + { + lock (EntityPool.PedsLock) + { + EntityPool.Add(p); + } + } + public static void Add(SyncedProjectile sp) + { + lock (EntityPool.ProjectilesLock) + { + EntityPool.Add(sp); + } + } + } } } diff --git a/Client/Sync/EventArgs/ProjectileShotEventArgs.cs b/Client/Sync/EventArgs/ProjectileShotEventArgs.cs index d207184..a6f45b2 100644 --- a/Client/Sync/EventArgs/ProjectileShotEventArgs.cs +++ b/Client/Sync/EventArgs/ProjectileShotEventArgs.cs @@ -10,5 +10,7 @@ namespace RageCoop.Client { public bool IsMine { get; set; } public Projectile Projectile { get; set; } + + public SyncedPed Owner { get; set; } } } diff --git a/Client/Sync/SyncEvents.cs b/Client/Sync/SyncEvents.cs index 35cefee..afbc4ac 100644 --- a/Client/Sync/SyncEvents.cs +++ b/Client/Sync/SyncEvents.cs @@ -12,17 +12,7 @@ using System.Threading; namespace RageCoop.Client { internal static class SyncEvents { - public static event EventHandler OnProjectileShot; - static SyncEvents() { - OnProjectileShot+=(s, e) => - { - if (e.IsMine) - { - TriggerProjectileShot(e.Projectile); - } - }; - } #region TRIGGER public static void TriggerPedKilled(SyncedPed victim) { @@ -69,6 +59,8 @@ namespace RageCoop.Client { public static void TriggerBulletShot(uint hash,SyncedPed owner,Vector3 impactPosition) { + Main.Logger.Trace($"bullet shot:{(WeaponHash)hash}"); + // Minigun, not working for some reason if (hash==(uint)WeaponHash.Minigun) { @@ -100,17 +92,6 @@ namespace RageCoop.Client { } - public static void TriggerProjectileShot(Projectile p) - { - var pp = p.Owner; - if (pp.IsShooting) - { - - var start = p.Position; - var end = start+p.Velocity; - Networking.SendBulletShot(start, end, (uint)p.WeaponHash, pp.GetSyncEntity().ID); - } - } #endregion #region HANDLE @@ -135,8 +116,16 @@ namespace RageCoop.Client { public static void HandleEnteredVehicle(int pedId, int vehId, VehicleSeat seat) { var v = EntityPool.GetVehicleByID(vehId); - if (v==null) { return; } - EntityPool.GetPedByID(pedId)?.MainPed?.SetIntoVehicle(v.MainVehicle, seat); + var p = EntityPool.GetPedByID(pedId)?.MainPed; + if (v==null||p==null) { return; } + if (!v.MainVehicle.IsSeatFree(seat)) + { + if (v.MainVehicle.GetPedOnSeat(seat)!=p) + { + v.MainVehicle.GetPedOnSeat(seat).Task.WarpOutOfVehicle(v.MainVehicle); + } + } + p.SetIntoVehicle(v.MainVehicle, seat); } public static void HandleOwnerChanged(Packets.OwnerChanged p) { @@ -269,46 +258,11 @@ namespace RageCoop.Client { */ #region CHECK EVENTS - static bool _projectileShot = false; - static Projectile[] lastProjectiles=new Projectile[0]; - public static void CheckProjectiles() - { - Projectile[] projectiles = World.GetAllProjectiles(); - - _projectileShot=false; - foreach (Projectile p in projectiles) - { - var owner = p.Owner?.GetSyncEntity(); - if (!lastProjectiles.Contains(p)) - { - if((owner!=null) && owner.IsMine) - { - _projectileShot=true; - OnProjectileShot?.Invoke(null, new ProjectileShotEventArgs() - { - Projectile=p, - IsMine=true - }) ; - } - else - { - OnProjectileShot?.Invoke(null, new ProjectileShotEventArgs() - { - Projectile=p, - IsMine=false - }); - } - } - - } - - lastProjectiles=projectiles; - } public static void Check(SyncedPed c) { Ped subject = c.MainPed; - if (subject.IsShooting && !_projectileShot) + if (subject.IsShooting && !subject.IsUsingProjectileWeapon()) { int i = 0; Func getBulletImpact = (() => diff --git a/Client/WorldThread.cs b/Client/WorldThread.cs index d5339c4..cf70bce 100644 --- a/Client/WorldThread.cs +++ b/Client/WorldThread.cs @@ -42,8 +42,8 @@ namespace RageCoop.Client Function.Call(Hash.SET_DEEP_OCEAN_SCALER, 0.0f); // Works only ~200 meters around the player Function.Call(Hash.SET_CAN_ATTACK_FRIENDLY, Game.Player.Character.Handle, true, false); - - if (Main.DisableTraffic) + if (Main.Settings==null) { return; } + if (Main.Settings.DisableTraffic) { if (!_lastDisableTraffic) { @@ -63,7 +63,7 @@ namespace RageCoop.Client Traffic(true); } - _lastDisableTraffic = Main.DisableTraffic; + _lastDisableTraffic = Main.Settings.DisableTraffic; } private void Traffic(bool enable) diff --git a/Core/Packets/Packets.cs b/Core/Packets/Packets.cs index 02f11e3..99151c9 100644 --- a/Core/Packets/Packets.cs +++ b/Core/Packets/Packets.cs @@ -117,6 +117,7 @@ namespace RageCoop.Core Handshake=0, PlayerConnect=1, PlayerDisconnect=2, + PlayerInfoUpdate=3, ChatMessage=10, NativeCall=11, @@ -133,8 +134,8 @@ namespace RageCoop.Core #region INTERVAL VehicleSync = 20, VehicleStateSync = 21, - CharacterSync = 22, - CharacterStateSync = 23, + PedSync = 22, + PedStateSync = 23, ProjectileSync=24, #endregion @@ -169,15 +170,9 @@ namespace RageCoop.Core File = 8, Event = 9, VehicleSync=20, - CharacterSync=21, - SyncEvents=30, - ///obsolete - /* - PlayerLight = 1, - PlayerFull = 2, - PlayerSuperLight = 3, - NPCFull = 4, - */ + PedSync=21, + ProjectileSync = 22, + SyncEvents =30, } [Flags] diff --git a/Core/Packets/PedPackets.cs b/Core/Packets/PedPackets.cs index 0775a98..6119df3 100644 --- a/Core/Packets/PedPackets.cs +++ b/Core/Packets/PedPackets.cs @@ -30,7 +30,7 @@ namespace RageCoop.Core public override void Pack(NetOutgoingMessage message) { #region PacketToNetOutGoingMessage - message.Write((byte)PacketTypes.CharacterStateSync); + message.Write((byte)PacketTypes.PedStateSync); List byteArray = new List(); @@ -145,7 +145,7 @@ namespace RageCoop.Core public override void Pack(NetOutgoingMessage message) { #region PacketToNetOutGoingMessage - message.Write((byte)PacketTypes.CharacterSync); + message.Write((byte)PacketTypes.PedSync); List byteArray = new List(); diff --git a/Core/Packets/PlayerPackets.cs b/Core/Packets/PlayerPackets.cs index a8ceb9b..6b2a06c 100644 --- a/Core/Packets/PlayerPackets.cs +++ b/Core/Packets/PlayerPackets.cs @@ -147,17 +147,18 @@ namespace RageCoop.Core } } - public class PlayerPedID : Packet + public class PlayerInfoUpdate : Packet { /// /// Ped ID for this Player /// public int PedID { get; set; } public string Username { get; set; } + public float Latency { get; set; } public override void Pack(NetOutgoingMessage message) { #region PacketToNetOutGoingMessage - message.Write((byte)PacketTypes.PlayerConnect); + message.Write((byte)PacketTypes.PlayerInfoUpdate); List byteArray = new List(); @@ -167,12 +168,16 @@ namespace RageCoop.Core // Get Username bytes byte[] usernameBytes = Encoding.UTF8.GetBytes(Username); + // Write UsernameLength byteArray.AddRange(BitConverter.GetBytes(usernameBytes.Length)); // Write Username byteArray.AddRange(usernameBytes); + // Write Latency + byteArray.AddFloat(Latency); + byte[] result = byteArray.ToArray(); message.Write(result.Length); @@ -190,6 +195,8 @@ namespace RageCoop.Core // Read Username int usernameLength = reader.ReadInt(); Username = reader.ReadString(usernameLength); + + Latency=reader.ReadFloat(); } } } diff --git a/Core/Packets/ProjectileSync.cs b/Core/Packets/ProjectileSync.cs index 92763a6..7429da1 100644 --- a/Core/Packets/ProjectileSync.cs +++ b/Core/Packets/ProjectileSync.cs @@ -5,63 +5,89 @@ using Lidgren.Network; namespace RageCoop.Core { - internal class ProjectileSync:Packet + public partial class Packets { - - public int ID { get; set; } - - public LVector3 Position { get; set; } - - public LVector3 Rotation { get; set; } - - public LVector3 Velocity { get; set; } - - - public override void Pack(NetOutgoingMessage message) + public class ProjectileSync : Packet { - #region PacketToNetOutGoingMessage - message.Write((byte)PacketTypes.ProjectileSync); - List byteArray = new List(); + public int ID { get; set; } - // Write vehicle id - byteArray.AddInt(ID); + public int ShooterID { get; set; } + public uint WeaponHash { get; set; } - // Write position - byteArray.AddLVector3(Position); + public LVector3 Position { get; set; } + + public LVector3 Rotation { get; set; } + + public LVector3 Velocity { get; set; } + + public bool Exploded { get; set; } - // Write rotation - byteArray.AddLVector3(Rotation); - // Write velocity - byteArray.AddLVector3(Velocity); + public override void Pack(NetOutgoingMessage message) + { + #region PacketToNetOutGoingMessage + message.Write((byte)PacketTypes.ProjectileSync); - byte[] result = byteArray.ToArray(); + List byteArray = new List(); - message.Write(result.Length); - message.Write(result); - #endregion - } + // Write id + byteArray.AddInt(ID); - public override void Unpack(byte[] array) - { - #region NetIncomingMessageToPacket - BitReader reader = new BitReader(array); + // Write ShooterID + byteArray.AddInt(ShooterID); - // Read id - ID = reader.ReadInt(); + byteArray.AddUint(WeaponHash); - // Read position - Position = reader.ReadLVector3(); + // Write position + byteArray.AddLVector3(Position); - // Read rotation - Rotation = reader.ReadLVector3(); - // Read velocity - Velocity =reader.ReadLVector3(); + // Write rotation + byteArray.AddLVector3(Rotation); - #endregion + // Write velocity + byteArray.AddLVector3(Velocity); + + if (Exploded) { byteArray.Add(1); } + + byte[] result = byteArray.ToArray(); + + message.Write(result.Length); + message.Write(result); + #endregion + } + + public override void Unpack(byte[] array) + { + #region NetIncomingMessageToPacket + BitReader reader = new BitReader(array); + + // Read id + ID = reader.ReadInt(); + + // Read ShooterID + ShooterID= reader.ReadInt(); + + WeaponHash= reader.ReadUInt(); + + // Read position + Position = reader.ReadLVector3(); + + // Read rotation + Rotation = reader.ReadLVector3(); + + // Read velocity + Velocity =reader.ReadLVector3(); + + if (reader.CanRead(1)) + { + Exploded=true; + } + + #endregion + } } } } diff --git a/Core/PlayerData.cs b/Core/PlayerData.cs index ea18e49..4a5d40b 100644 --- a/Core/PlayerData.cs +++ b/Core/PlayerData.cs @@ -19,7 +19,11 @@ namespace RageCoop.Core public int VehicleID { get; set; } public bool IsInVehicle { get; internal set; } public LVector3 Position { get; set; } - public int Latency { get; set; } + + /// + /// Player Latency in second. + /// + public float Latency { get; set; } public int Health { get; set; } public bool IsInRangeOf(LVector3 position, float distance) diff --git a/Server/Properties/PublishProfiles/FolderProfile.pubxml b/Server/Properties/PublishProfiles/FolderProfile.pubxml index bd4d9b8..f262f64 100644 --- a/Server/Properties/PublishProfiles/FolderProfile.pubxml +++ b/Server/Properties/PublishProfiles/FolderProfile.pubxml @@ -6,13 +6,12 @@ https://go.microsoft.com/fwlink/?LinkID=208121. Release Any CPU - bin\Release\net6.0\publish\win-x64\ + bin\Release\net6.0\publish\linux-x64\ FileSystem net6.0 - win-x64 + linux-x64 true True - True True \ No newline at end of file diff --git a/Server/Properties/PublishProfiles/FolderProfile.pubxml.user b/Server/Properties/PublishProfiles/FolderProfile.pubxml.user index e87829c..4e5d7cc 100644 --- a/Server/Properties/PublishProfiles/FolderProfile.pubxml.user +++ b/Server/Properties/PublishProfiles/FolderProfile.pubxml.user @@ -4,6 +4,6 @@ https://go.microsoft.com/fwlink/?LinkID=208121. --> - True|2022-05-22T08:56:31.0481188Z;True|2022-05-18T13:35:57.1402751+08:00;True|2022-05-18T13:10:28.4995253+08:00;True|2022-05-01T18:35:01.9624101+08:00;True|2022-05-01T12:32:20.8671319+08:00;False|2022-05-01T12:30:25.4596227+08:00; + True|2022-05-24T03:00:13.3617113Z;True|2022-05-22T16:56:31.0481188+08:00;True|2022-05-18T13:35:57.1402751+08:00;True|2022-05-18T13:10:28.4995253+08:00;True|2022-05-01T18:35:01.9624101+08:00;True|2022-05-01T12:32:20.8671319+08:00;False|2022-05-01T12:30:25.4596227+08:00; \ No newline at end of file diff --git a/Server/Server.cs b/Server/Server.cs index eb13733..610b168 100644 --- a/Server/Server.cs +++ b/Server/Server.cs @@ -34,6 +34,7 @@ namespace RageCoop.Server public static Resource RunningResource = null; public static readonly Dictionary> Commands = new(); public static readonly Dictionary> TriggerEvents = new(); + private static Thread BackgroundThread; public static readonly List Clients = new(); @@ -210,6 +211,8 @@ namespace RageCoop.Server DownloadManager.CheckForDirectoryAndFiles(); Listen(); + + BackgroundThread=new Thread(() => Background()); } private void Listen() @@ -304,7 +307,7 @@ namespace RageCoop.Server #region SyncData - case PacketTypes.CharacterStateSync: + case PacketTypes.PedStateSync: { try { @@ -340,7 +343,7 @@ namespace RageCoop.Server } } break; - case PacketTypes.CharacterSync: + case PacketTypes.PedSync: { try { @@ -376,6 +379,23 @@ namespace RageCoop.Server } } break; + case PacketTypes.ProjectileSync: + { + try + { + int len = message.ReadInt32(); + byte[] data = message.ReadBytes(len); + + Packets.ProjectileSync packet = new(); + packet.Unpack(data); + ProjectileSync(packet, message.SenderConnection.RemoteUniqueIdentifier); + } + catch (Exception e) + { + DisconnectAndLog(message.SenderConnection, type, e); + } + } + break; #endregion @@ -563,7 +583,7 @@ namespace RageCoop.Server MainNetServer.Connections.FindAll(x => x.RemoteUniqueIdentifier != message.SenderConnection.RemoteUniqueIdentifier).ForEach(x => { - MainNetServer.SendMessage(outgoingMessage, x, NetDeliveryMethod.UnreliableSequenced, (byte)ConnectionChannel.CharacterSync); + MainNetServer.SendMessage(outgoingMessage, x, NetDeliveryMethod.UnreliableSequenced, (byte)ConnectionChannel.PedSync); }); } @@ -629,6 +649,29 @@ namespace RageCoop.Server Thread.Sleep(1000); } } + private void Background() + { + while (true) + { + foreach(Client c in Clients) + { + MainNetServer.Connections.FindAll(x => x.RemoteUniqueIdentifier != c.ClientID).ForEach(x => + { + NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage(); + new Packets.PlayerInfoUpdate() + { + PedID=c.Player.PedID, + Username=c.Player.Username, + Latency=c.Player.Latency=c.Latency, + }.Pack(outgoingMessage); + MainNetServer.SendMessage(outgoingMessage, x, NetDeliveryMethod.ReliableSequenced, (byte)ConnectionChannel.Default); + }); + } + + // Update Latency every 20 seconds. + Thread.Sleep(1000*20); + } + } private void DisconnectAndLog(NetConnection senderConnection,PacketTypes type, Exception e) { @@ -830,7 +873,7 @@ namespace RageCoop.Server { NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage(); packet.Pack(outgoingMessage); - MainNetServer.SendMessage(outgoingMessage, x, NetDeliveryMethod.UnreliableSequenced, (byte)ConnectionChannel.CharacterSync); + MainNetServer.SendMessage(outgoingMessage, x, NetDeliveryMethod.UnreliableSequenced, (byte)ConnectionChannel.PedSync); }); @@ -839,7 +882,6 @@ namespace RageCoop.Server RunningResource.InvokePlayerUpdate(client); } } - private static void VehicleStateSync(Packets.VehicleStateSync packet, long ClientID) { Client client = Util.GetClientByID(ClientID); @@ -862,7 +904,6 @@ namespace RageCoop.Server }); } - private static void CharacterSync(Packets.PedSync packet, long ClientID) { Client client = Util.GetClientByID(ClientID); @@ -877,7 +918,7 @@ namespace RageCoop.Server { NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage(); packet.Pack(outgoingMessage); - MainNetServer.SendMessage(outgoingMessage, x, NetDeliveryMethod.UnreliableSequenced, (byte)ConnectionChannel.CharacterSync); + MainNetServer.SendMessage(outgoingMessage, x, NetDeliveryMethod.UnreliableSequenced, (byte)ConnectionChannel.PedSync); }); @@ -886,7 +927,6 @@ namespace RageCoop.Server RunningResource.InvokePlayerUpdate(client); } } - private static void VehicleSync(Packets.VehicleSync packet, long ClientID) { Client client = Util.GetClientByID(ClientID); @@ -932,177 +972,22 @@ namespace RageCoop.Server } */ } - #region Obsolete - /* - private static void FullSyncPlayer(Packets.FullSyncPlayer packet) + private static void ProjectileSync(Packets.ProjectileSync packet, long ClientID) { - Client client = Util.GetClientByNetHandle(packet.NetHandle); + Client client = Util.GetClientByID(ClientID); if (client == null) { return; } - // Save the new data - client.Player.PedHandle = packet.PedHandle; - client.Player.IsInVehicle = false; - client.Player.Position = packet.Position; - client.Player.Health = packet.Health; - // Override the latency - packet.Latency = client.Latency; - - MainNetServer.Connections.FindAll(x => x.RemoteUniqueIdentifier != packet.NetHandle).ForEach(x => + MainNetServer.Connections.FindAll(x => x.RemoteUniqueIdentifier != ClientID).ForEach(x => { NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage(); - if (Clients.First(y => y.NetHandle == x.RemoteUniqueIdentifier).Player.IsInRangeOf(packet.Position, 550f)) - { - packet.PacketToNetOutGoingMessage(outgoingMessage); - MainNetServer.SendMessage(outgoingMessage, x, NetDeliveryMethod.UnreliableSequenced, (byte)ConnectionChannel.PlayerFull); - } - else - { - new Packets.SuperLightSync() - { - NetHandle = packet.NetHandle, - Position = packet.Position, - Latency = packet.Latency - }.PacketToNetOutGoingMessage(outgoingMessage); - MainNetServer.SendMessage(outgoingMessage, x, NetDeliveryMethod.UnreliableSequenced, (byte)ConnectionChannel.PlayerSuperLight); - } + packet.Pack(outgoingMessage); + MainNetServer.SendMessage(outgoingMessage, x, NetDeliveryMethod.UnreliableSequenced, (byte)ConnectionChannel.ProjectileSync); }); - - if (RunningResource != null) - { - RunningResource.InvokePlayerUpdate(client); - } } - private static void FullSyncPlayerVeh(Packets.FullSyncPlayerVeh packet) - { - Client client = Util.GetClientByNetHandle(packet.NetHandle); - if (client == null) - { - return; - } - // Save the new data - client.Player.PedHandle = packet.PedHandle; - client.Player.VehicleHandle = packet.VehicleHandle; - client.Player.IsInVehicle = true; - client.Player.Position = packet.Position; - client.Player.Health = packet.Health; - - // Override the latency - packet.Latency = client.Latency; - - MainNetServer.Connections.FindAll(x => x.RemoteUniqueIdentifier != packet.NetHandle).ForEach(x => - { - NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage(); - - if (Clients.First(y => y.NetHandle == x.RemoteUniqueIdentifier).Player.IsInRangeOf(packet.Position, 550f)) - { - packet.PacketToNetOutGoingMessage(outgoingMessage); - MainNetServer.SendMessage(outgoingMessage, x, NetDeliveryMethod.UnreliableSequenced, (byte)ConnectionChannel.PlayerFull); - } - else - { - new Packets.SuperLightSync() - { - NetHandle = packet.NetHandle, - Position = packet.Position, - Latency = packet.Latency - }.PacketToNetOutGoingMessage(outgoingMessage); - MainNetServer.SendMessage(outgoingMessage, x, NetDeliveryMethod.UnreliableSequenced, (byte)ConnectionChannel.PlayerSuperLight); - } - }); - - if (RunningResource != null) - { - RunningResource.InvokePlayerUpdate(client); - } - } - - private static void LightSyncPlayer(Packets.LightSyncPlayer packet) - { - Client client = Util.GetClientByNetHandle(packet.NetHandle); - if (client == null) - { - return; - } - // Save the new data - client.Player.Position = packet.Position; - client.Player.Health = packet.Health; - - // Override the latency - packet.Latency = client.Latency; - - MainNetServer.Connections.FindAll(x => x.RemoteUniqueIdentifier != packet.NetHandle).ForEach(x => - { - NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage(); - - if (Clients.First(y => y.NetHandle == x.RemoteUniqueIdentifier).Player.IsInRangeOf(packet.Position, 550f)) - { - packet.PacketToNetOutGoingMessage(outgoingMessage); - MainNetServer.SendMessage(outgoingMessage, x, NetDeliveryMethod.UnreliableSequenced, (byte)ConnectionChannel.PlayerLight); - } - else - { - new Packets.SuperLightSync() - { - NetHandle = packet.NetHandle, - Position = packet.Position, - Latency = packet.Latency - }.PacketToNetOutGoingMessage(outgoingMessage); - MainNetServer.SendMessage(outgoingMessage, x, NetDeliveryMethod.UnreliableSequenced, (byte)ConnectionChannel.PlayerSuperLight); - } - }); - - if (RunningResource != null) - { - RunningResource.InvokePlayerUpdate(client); - } - } - - private static void LightSyncPlayerVeh(Packets.LightSyncPlayerVeh packet) - { - Client client = Util.GetClientByNetHandle(packet.NetHandle); - if (client == null) - { - return; - } - // Save the new data - client.Player.Position = packet.Position; - client.Player.Health = packet.Health; - - // Override the latency - packet.Latency = client.Latency; - - MainNetServer.Connections.FindAll(x => x.RemoteUniqueIdentifier != packet.NetHandle).ForEach(x => - { - NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage(); - - if (Clients.First(y => y.NetHandle == x.RemoteUniqueIdentifier).Player.IsInRangeOf(packet.Position, 550f)) - { - packet.PacketToNetOutGoingMessage(outgoingMessage); - MainNetServer.SendMessage(outgoingMessage, x, NetDeliveryMethod.UnreliableSequenced, (byte)ConnectionChannel.PlayerLight); - } - else - { - new Packets.SuperLightSync() - { - NetHandle = packet.NetHandle, - Position = packet.Position, - Latency = packet.Latency - }.PacketToNetOutGoingMessage(outgoingMessage); - MainNetServer.SendMessage(outgoingMessage, x, NetDeliveryMethod.UnreliableSequenced, (byte)ConnectionChannel.PlayerSuperLight); - } - }); - - if (RunningResource != null) - { - RunningResource.InvokePlayerUpdate(client); - } - } - */ - #endregion #endregion // Send a message to targets or all players private static void SendChatMessage(Packets.ChatMessage packet, List targets = null)