Big update! Projectile sync, latency and weapon fix

This commit is contained in:
sausage
2022-05-25 10:09:59 +08:00
parent 7854a47569
commit f4e9767184
25 changed files with 546 additions and 501 deletions

View File

@ -243,7 +243,7 @@ namespace RageCoop.Client
/// <param name="enable">true to disable traffic</param>
public static void SetLocalTraffic(bool enable)
{
Main.DisableTraffic = !enable;
Main.Settings.DisableTraffic = !enable;
}
/// <summary>

View File

@ -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;

View File

@ -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;
}

View File

@ -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)

View File

@ -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<WeaponHash> ProjectileWeapons = new HashSet<WeaponHash> {
WeaponHash.HomingLauncher,
WeaponHash.RPG,
WeaponHash.Firework,
WeaponHash.UpNAtomizer,
WeaponHash.GrenadeLauncher,
WeaponHash.GrenadeLauncherSmoke,
WeaponHash.CompactGrenadeLauncher
};
/*
public static readonly Dictionary<WeaponHash, ExplosionType> WeaponExplosionTypes = new Dictionary<WeaponHash, ExplosionType> {
{ 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},
};
*/
}
/// <summary>
///

View File

@ -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;

View File

@ -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<VehicleSeat, SyncedPed>();
v.LockStatus=packet.LockStatus;
foreach (KeyValuePair<int, int> 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<VehicleSeat, SyncedPed>();
v.LockStatus=packet.LockStatus;
foreach (KeyValuePair<int, int> 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;
}
}
}

View File

@ -11,23 +11,24 @@ using GTA.Math;
namespace RageCoop.Client
{
public static partial class Networking
internal static partial class Networking
{
#region -- SEND --
/// <summary>
/// Pack the packet then send to server.
/// </summary>
/// <param name="p"></param>
/// <param name="channel"></param>
/// <param name="method"></param>
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)

View File

@ -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);
}
}

View File

@ -40,5 +40,11 @@ namespace RageCoop.Client
/// </summary>
public Keys PassengerKey { get; set; }=Keys.G;
/// <summary>
/// Disable world NPC traffic, mission entities won't be affected
/// </summary>
public bool DisableTraffic { get; set; } = true;
}
}

View File

@ -24,15 +24,7 @@ namespace RageCoop.Client
/// <param name="p"></param>
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<int>(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<int>(Hash.CREATE_WEAPON_OBJECT, CurrentWeaponHash, -1, Position.X, Position.Y, Position.Z, true, 0, 0);
foreach (KeyValuePair<uint, bool> 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;

View File

@ -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; }
/// <summary>
/// Invalid property for projectile.
/// </summary>
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<ProjectileShotEventArgs> 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);
}
}
}

View File

@ -22,15 +22,8 @@ namespace RageCoop.Client
/// <param name="p"></param>
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;

View File

@ -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<int, SyncedVehicle> ID_Vehicles = new Dictionary<int, SyncedVehicle>();
private static Dictionary<int, SyncedVehicle> Handle_Vehicles = new Dictionary<int, SyncedVehicle>();
public static object ProjectilesLock = new object();
private static Dictionary<int, SyncedProjectile> ID_Projectiles = new Dictionary<int, SyncedProjectile>();
private static Dictionary<int, SyncedProjectile> Handle_Projectiles = new Dictionary<int, SyncedProjectile>();
public static void Cleanup(bool keepPlayer=true,bool keepMine=true)
{
foreach(int id in new List<int>(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);
}
}
}
}
}

View File

@ -10,5 +10,7 @@ namespace RageCoop.Client
{
public bool IsMine { get; set; }
public Projectile Projectile { get; set; }
public SyncedPed Owner { get; set; }
}
}

View File

@ -12,17 +12,7 @@ using System.Threading;
namespace RageCoop.Client {
internal static class SyncEvents
{
public static event EventHandler<ProjectileShotEventArgs> 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<bool> getBulletImpact = (() =>

View File

@ -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)

View File

@ -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]

View File

@ -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<byte> byteArray = new List<byte>();
@ -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<byte> byteArray = new List<byte>();

View File

@ -147,17 +147,18 @@ namespace RageCoop.Core
}
}
public class PlayerPedID : Packet
public class PlayerInfoUpdate : Packet
{
/// <summary>
/// Ped ID for this Player
/// </summary>
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<byte> byteArray = new List<byte>();
@ -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();
}
}
}

View File

@ -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<byte> byteArray = new List<byte>();
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<byte> byteArray = new List<byte>();
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
}
}
}
}

View File

@ -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; }
/// <summary>
/// Player Latency in second.
/// </summary>
public float Latency { get; set; }
public int Health { get; set; }
public bool IsInRangeOf(LVector3 position, float distance)

View File

@ -6,13 +6,12 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
<PropertyGroup>
<Configuration>Release</Configuration>
<Platform>Any CPU</Platform>
<PublishDir>bin\Release\net6.0\publish\win-x64\</PublishDir>
<PublishDir>bin\Release\net6.0\publish\linux-x64\</PublishDir>
<PublishProtocol>FileSystem</PublishProtocol>
<TargetFramework>net6.0</TargetFramework>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<RuntimeIdentifier>linux-x64</RuntimeIdentifier>
<SelfContained>true</SelfContained>
<PublishSingleFile>True</PublishSingleFile>
<PublishReadyToRun>True</PublishReadyToRun>
<PublishTrimmed>True</PublishTrimmed>
</PropertyGroup>
</Project>

View File

@ -4,6 +4,6 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<History>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;</History>
<History>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;</History>
</PropertyGroup>
</Project>

View File

@ -34,6 +34,7 @@ namespace RageCoop.Server
public static Resource RunningResource = null;
public static readonly Dictionary<Command, Action<CommandContext>> Commands = new();
public static readonly Dictionary<TriggerEvent, Action<EventContext>> TriggerEvents = new();
private static Thread BackgroundThread;
public static readonly List<Client> 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<NetConnection> targets = null)