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)