420 lines
19 KiB
C#
Raw Normal View History

2022-07-20 17:50:01 +08:00
using GTA;
2022-05-22 15:55:26 +08:00
using Lidgren.Network;
using RageCoop.Client.Menus;
2022-07-20 17:50:01 +08:00
using RageCoop.Core;
using System;
using System.Collections.Generic;
2022-06-24 10:33:36 +08:00
using System.Threading;
2022-05-22 15:55:26 +08:00
namespace RageCoop.Client
{
internal static partial class Networking
2022-05-22 15:55:26 +08:00
{
2022-08-11 18:25:01 +08:00
private static PacketPool PacketPool=new PacketPool();
2022-07-13 10:36:38 +08:00
private static readonly Func<byte, BitReader, object> _resolveHandle = (t, reader) =>
2022-07-04 09:54:43 +08:00
{
switch (t)
{
case 50:
2022-08-06 11:40:38 +08:00
return EntityPool.ServerProps[reader.ReadInt32()].MainProp?.Handle;
2022-07-04 09:54:43 +08:00
case 51:
2022-08-06 11:40:38 +08:00
return EntityPool.GetPedByID(reader.ReadInt32())?.MainPed?.Handle;
2022-07-04 09:54:43 +08:00
case 52:
2022-08-06 11:40:38 +08:00
return EntityPool.GetVehicleByID(reader.ReadInt32())?.MainVehicle?.Handle;
2022-07-04 09:54:43 +08:00
case 60:
2022-08-06 11:40:38 +08:00
return EntityPool.ServerBlips[reader.ReadInt32()].Handle;
2022-07-04 09:54:43 +08:00
default:
throw new ArgumentException("Cannot resolve server side argument: "+t);
}
};
2022-07-20 17:50:01 +08:00
private static readonly AutoResetEvent _publicKeyReceived = new AutoResetEvent(false);
public static void ProcessMessage(NetIncomingMessage message)
2022-05-22 15:55:26 +08:00
{
2022-07-20 17:50:01 +08:00
if (message == null) { return; }
2022-05-22 15:55:26 +08:00
switch (message.MessageType)
2022-05-22 15:55:26 +08:00
{
case NetIncomingMessageType.StatusChanged:
NetConnectionStatus status = (NetConnectionStatus)message.ReadByte();
string reason = message.ReadString();
switch (status)
{
case NetConnectionStatus.InitiatedConnect:
2022-08-08 17:03:41 +08:00
if (message.SenderConnection==ServerConnection)
{
CoopMenu.InitiateConnectionMenuSetting();
}
break;
case NetConnectionStatus.Connected:
2022-08-08 17:03:41 +08:00
if (message.SenderConnection==ServerConnection)
2022-07-20 17:50:01 +08:00
{
2022-08-08 17:03:41 +08:00
Memory.ApplyPatches();
var response = message.SenderConnection.RemoteHailMessage;
if ((PacketType)response.ReadByte()!=PacketType.HandshakeSuccess)
{
throw new Exception("Invalid handshake response!");
}
var p = new Packets.HandshakeSuccess();
p.Deserialize(response.ReadBytes(response.ReadInt32()));
foreach(var player in p.Players)
{
PlayerList.SetPlayer(player.ID,player.Username);
}
Main.QueueAction(() =>
{
CoopMenu.ConnectedMenuSetting();
Main.MainChat.Init();
GTA.UI.Notification.Show("~g~Connected!");
});
Main.Logger.Info(">> Connected <<");
}
2022-08-10 20:42:47 +08:00
else
2022-08-08 17:03:41 +08:00
{
2022-08-10 20:42:47 +08:00
// Self-initiated connection
if (message.SenderConnection.RemoteHailMessage==null) { return; }
var p = message.SenderConnection.RemoteHailMessage.GetPacket<Packets.P2PConnect>();
if (PlayerList.Players.TryGetValue(p.ID,out var player))
{
player.Connection=message.SenderConnection;
Main.Logger.Debug($"Direct connectionn to {player.Username} established");
}
else
2022-08-08 17:03:41 +08:00
{
2022-08-10 20:42:47 +08:00
Main.Logger.Info($"Unidentified peer connection from {message.SenderEndPoint} was rejected.");
message.SenderConnection.Disconnect("eat poop");
}
2022-08-08 17:03:41 +08:00
}
break;
case NetConnectionStatus.Disconnected:
2022-08-06 12:32:04 +08:00
if (message.SenderConnection==ServerConnection)
{
2022-08-06 12:32:04 +08:00
Memory.RestorePatches();
DownloadManager.Cleanup();
if (Main.MainChat.Focused)
{
Main.MainChat.Focused = false;
}
Main.QueueAction(() => Main.CleanUp());
CoopMenu.DisconnectedMenuSetting();
Main.Logger.Info($">> Disconnected << reason: {reason}");
2022-08-11 14:59:09 +02:00
Main.QueueAction(() => GTA.UI.Notification.Show("~r~Disconnected: " + reason));
2022-08-06 12:32:04 +08:00
Main.Resources.Unload();
}
break;
}
break;
case NetIncomingMessageType.Data:
{
2022-06-24 10:33:36 +08:00
if (message.LengthBytes==0) { break; }
2022-07-01 12:22:31 +08:00
var packetType = PacketType.Unknown;
2022-06-24 10:33:36 +08:00
try
2022-05-22 15:55:26 +08:00
{
2022-07-01 12:22:31 +08:00
// Get packet type
packetType = (PacketType)message.ReadByte();
2022-06-24 10:33:36 +08:00
switch (packetType)
{
2022-07-01 12:22:31 +08:00
case PacketType.Response:
2022-06-24 10:33:36 +08:00
{
2022-07-01 12:22:31 +08:00
int id = message.ReadInt32();
if (PendingResponses.TryGetValue(id, out var callback))
{
callback((PacketType)message.ReadByte(), message.ReadBytes(message.ReadInt32()));
PendingResponses.Remove(id);
}
2022-06-24 10:33:36 +08:00
break;
}
2022-07-01 12:22:31 +08:00
case PacketType.Request:
2022-06-24 10:33:36 +08:00
{
2022-07-01 12:22:31 +08:00
int id = message.ReadInt32();
var realType = (PacketType)message.ReadByte();
int len = message.ReadInt32();
if (RequestHandlers.TryGetValue(realType, out var handler))
{
2022-08-06 12:32:04 +08:00
var response = Peer.CreateMessage();
2022-07-01 12:22:31 +08:00
response.Write((byte)PacketType.Response);
response.Write(id);
handler(message.ReadBytes(len)).Pack(response);
2022-08-06 12:32:04 +08:00
Peer.SendMessage(response,ServerConnection, NetDeliveryMethod.ReliableOrdered, message.SequenceChannel);
Peer.FlushSendQueue();
2022-07-01 12:22:31 +08:00
}
2022-06-24 10:33:36 +08:00
break;
}
default:
{
2022-07-01 12:22:31 +08:00
byte[] data = message.ReadBytes(message.ReadInt32());
2022-08-08 17:03:41 +08:00
HandlePacket(packetType, data,message.SenderConnection);
2022-07-01 12:22:31 +08:00
break;
2022-06-24 10:33:36 +08:00
}
}
2022-05-22 15:55:26 +08:00
}
2022-06-24 10:33:36 +08:00
catch (Exception ex)
{
2022-07-20 17:50:01 +08:00
Main.QueueAction(() =>
{
2022-06-24 10:33:36 +08:00
GTA.UI.Notification.Show("~r~~h~Packet Error");
return true;
});
Main.Logger.Error($"[{packetType}] {ex.Message}");
Main.Logger.Error(ex);
2022-08-06 12:32:04 +08:00
Peer.Shutdown($"Packet Error [{packetType}]");
2022-06-24 10:33:36 +08:00
}
break;
}
2022-06-24 10:33:36 +08:00
case NetIncomingMessageType.UnconnectedData:
{
2022-07-01 12:22:31 +08:00
var packetType = (PacketType)message.ReadByte();
2022-06-24 10:33:36 +08:00
int len = message.ReadInt32();
byte[] data = message.ReadBytes(len);
2022-08-10 20:42:47 +08:00
switch (packetType)
2022-06-24 10:33:36 +08:00
{
2022-07-20 17:50:01 +08:00
2022-08-10 20:42:47 +08:00
case PacketType.HolePunch:
{
HolePunch.Punched(data.GetPacket<Packets.HolePunch>(), message.SenderEndPoint);
break;
}
case PacketType.PublicKeyResponse:
{
var packet = data.GetPacket<Packets.PublicKeyResponse>();
Security.SetServerPublicKey(packet.Modulus, packet.Exponent);
_publicKeyReceived.Set();
break;
}
}
2022-06-24 10:33:36 +08:00
break;
}
case NetIncomingMessageType.DebugMessage:
case NetIncomingMessageType.ErrorMessage:
case NetIncomingMessageType.WarningMessage:
case NetIncomingMessageType.VerboseDebugMessage:
2022-08-08 17:03:41 +08:00
Main.Logger.Trace(message.ReadString());
break;
default:
break;
2022-05-22 15:55:26 +08:00
}
2022-08-06 12:32:04 +08:00
Peer.Recycle(message);
2022-05-22 15:55:26 +08:00
}
2022-08-11 18:25:01 +08:00
static Packet packet;
2022-08-08 17:03:41 +08:00
private static void HandlePacket(PacketType packetType, byte[] data, NetConnection senderConnection)
2022-07-01 12:22:31 +08:00
{
switch (packetType)
{
2022-08-10 20:42:47 +08:00
case PacketType.HolePunchInit:
HolePunch.Add(data.GetPacket<Packets.HolePunchInit>());
2022-07-01 12:22:31 +08:00
break;
2022-08-10 20:42:47 +08:00
case PacketType.PlayerConnect:
PlayerConnect(data.GetPacket<Packets.PlayerConnect>());
2022-07-01 12:22:31 +08:00
break;
2022-08-10 20:42:47 +08:00
case PacketType.PlayerDisconnect:
PlayerDisconnect(data.GetPacket<Packets.PlayerDisconnect>());
break;
2022-07-01 12:22:31 +08:00
2022-08-10 20:42:47 +08:00
case PacketType.PlayerInfoUpdate:
PlayerList.UpdatePlayer(data.GetPacket<Packets.PlayerInfoUpdate>());
2022-07-01 12:22:31 +08:00
break;
2022-08-10 20:42:47 +08:00
case PacketType.VehicleSync:
2022-08-11 18:25:01 +08:00
packet = data.GetPacket<Packets.VehicleSync>(PacketPool);
VehicleSync((Packets.VehicleSync)packet);
PacketPool.Recycle((Packets.VehicleSync)packet);
2022-08-10 20:42:47 +08:00
break;
2022-07-01 12:22:31 +08:00
2022-08-10 20:42:47 +08:00
case PacketType.PedSync:
2022-08-11 18:25:01 +08:00
packet = data.GetPacket<Packets.PedSync>(PacketPool);
PedSync((Packets.PedSync)packet);
PacketPool.Recycle((Packets.PedSync)packet);
2022-07-01 12:22:31 +08:00
break;
case PacketType.ProjectileSync:
2022-08-10 20:42:47 +08:00
ProjectileSync(data.GetPacket<Packets.ProjectileSync>());
break;
2022-07-01 12:22:31 +08:00
case PacketType.ChatMessage:
{
2022-08-11 14:59:09 +02:00
Packets.ChatMessage packet = new Packets.ChatMessage((b) => Security.Decrypt(b));
2022-08-06 10:43:24 +08:00
packet.Deserialize(data);
2022-07-01 12:22:31 +08:00
Main.QueueAction(() => { Main.MainChat.AddMessage(packet.Username, packet.Message); return true; });
}
break;
2022-08-10 20:42:47 +08:00
2022-08-13 02:19:40 +02:00
case PacketType.Voice:
{
2022-08-13 03:39:11 +02:00
if (Main.Settings.Voice)
{
Packets.Voice packet = new Packets.Voice();
packet.Deserialize(data);
Main.QueueAction(() =>
{
Sync.Voice.AddVoiceData(packet.Buffer, packet.Recorded);
});
}
2022-08-13 02:19:40 +02:00
}
break;
2022-07-01 12:22:31 +08:00
case PacketType.CustomEvent:
{
2022-07-04 09:54:43 +08:00
Packets.CustomEvent packet = new Packets.CustomEvent(_resolveHandle);
2022-08-06 10:43:24 +08:00
packet.Deserialize(data);
2022-07-01 12:22:31 +08:00
Scripting.API.Events.InvokeCustomEventReceived(packet);
}
break;
2022-08-10 20:42:47 +08:00
2022-07-05 11:18:26 +08:00
case PacketType.CustomEventQueued:
{
Packets.CustomEvent packet = new Packets.CustomEvent(_resolveHandle);
Main.QueueAction(() =>
{
2022-08-06 10:43:24 +08:00
packet.Deserialize(data);
2022-07-05 11:18:26 +08:00
Scripting.API.Events.InvokeCustomEventReceived(packet);
});
}
break;
2022-08-10 20:42:47 +08:00
2022-07-01 12:22:31 +08:00
case PacketType.FileTransferChunk:
{
Packets.FileTransferChunk packet = new Packets.FileTransferChunk();
2022-08-06 10:43:24 +08:00
packet.Deserialize(data);
2022-07-01 12:22:31 +08:00
DownloadManager.Write(packet.ID, packet.FileChunk);
}
break;
2022-08-10 20:42:47 +08:00
2022-07-01 12:22:31 +08:00
default:
if (packetType.IsSyncEvent())
{
2022-08-10 20:42:47 +08:00
// Dispatch to script thread
2022-07-01 12:22:31 +08:00
Main.QueueAction(() => { SyncEvents.HandleEvent(packetType, data); return true; });
}
break;
}
}
private static void PedSync(Packets.PedSync packet)
2022-05-22 15:55:26 +08:00
{
SyncedPed c = EntityPool.GetPedByID(packet.ID);
if (c==null)
2022-05-22 15:55:26 +08:00
{
2022-07-11 11:59:32 +08:00
// Main.Logger.Debug($"Creating character for incoming sync:{packet.ID}");
EntityPool.ThreadSafe.Add(c=new SyncedPed(packet.ID));
}
2022-07-17 12:22:11 +08:00
PedDataFlags flags = packet.Flags;
c.ID=packet.ID;
c.OwnerID=packet.OwnerID;
c.Health = packet.Health;
c.Rotation = packet.Rotation;
c.Velocity = packet.Velocity;
c.Speed = packet.Speed;
2022-06-21 18:13:30 +08:00
c.IsAiming = flags.HasPedFlag(PedDataFlags.IsAiming);
c.IsReloading = flags.HasPedFlag(PedDataFlags.IsReloading);
c.IsJumping = flags.HasPedFlag(PedDataFlags.IsJumping);
c.IsRagdoll = flags.HasPedFlag(PedDataFlags.IsRagdoll);
c.IsOnFire = flags.HasPedFlag(PedDataFlags.IsOnFire);
c.IsInParachuteFreeFall = flags.HasPedFlag(PedDataFlags.IsInParachuteFreeFall);
c.IsParachuteOpen = flags.HasPedFlag(PedDataFlags.IsParachuteOpen);
c.IsOnLadder = flags.HasPedFlag(PedDataFlags.IsOnLadder);
c.IsVaulting = flags.HasPedFlag(PedDataFlags.IsVaulting);
c.IsInCover = flags.HasPedFlag(PedDataFlags.IsInCover);
c.IsInStealthMode = flags.HasPedFlag(PedDataFlags.IsInStealthMode);
c.Heading=packet.Heading;
2022-07-17 18:44:16 +08:00
c.Position = packet.Position;
if (c.IsRagdoll)
{
c.HeadPosition=packet.HeadPosition;
c.RightFootPosition=packet.RightFootPosition;
c.LeftFootPosition=packet.LeftFootPosition;
}
c.LastSynced = Main.Ticked;
if (c.IsAiming)
{
c.AimCoords = packet.AimCoords;
}
2022-07-17 12:22:11 +08:00
if (packet.Flags.HasPedFlag(PedDataFlags.IsFullSync))
{
2022-08-08 17:29:15 +08:00
c.CurrentWeaponHash = packet.CurrentWeaponHash;
c.Clothes=packet.Clothes;
c.WeaponComponents=packet.WeaponComponents;
c.WeaponTint=packet.WeaponTint;
c.Model=packet.ModelHash;
c.BlipColor=packet.BlipColor;
c.BlipSprite=packet.BlipSprite;
c.BlipScale=packet.BlipScale;
c.LastFullSynced = Main.Ticked;
2022-05-22 15:55:26 +08:00
}
2022-07-20 17:50:01 +08:00
2022-05-22 15:55:26 +08:00
}
private static void VehicleSync(Packets.VehicleSync packet)
2022-05-22 15:55:26 +08:00
{
2022-07-20 17:50:01 +08:00
SyncedVehicle v = EntityPool.GetVehicleByID(packet.ID);
if (v==null)
2022-05-22 15:55:26 +08:00
{
EntityPool.ThreadSafe.Add(v=new SyncedVehicle(packet.ID));
2022-05-22 15:55:26 +08:00
}
2022-07-02 17:14:56 +08:00
if (v.IsLocal) { return; }
v.ID= packet.ID;
v.OwnerID= packet.OwnerID;
2022-07-17 12:22:11 +08:00
v.Flags=packet.Flags;
v.Position=packet.Position;
2022-06-03 14:40:41 +08:00
v.Quaternion=packet.Quaternion;
v.SteeringAngle=packet.SteeringAngle;
v.ThrottlePower=packet.ThrottlePower;
v.BrakePower=packet.BrakePower;
v.Velocity=packet.Velocity;
v.RotationVelocity=packet.RotationVelocity;
v.DeluxoWingRatio=packet.DeluxoWingRatio;
v.LastSynced=Main.Ticked;
2022-07-17 19:19:23 +08:00
v.LastSyncedStopWatch.Restart();
2022-07-17 12:22:11 +08:00
if (packet.Flags.HasVehFlag(VehicleDataFlags.IsFullSync))
{
v.DamageModel=packet.DamageModel;
v.EngineHealth=packet.EngineHealth;
v.Mods=packet.Mods;
v.Model=packet.ModelHash;
v.Colors=packet.Colors;
v.LandingGear=packet.LandingGear;
v.RoofState=(VehicleRoofState)packet.RoofState;
v.Passengers=new Dictionary<VehicleSeat, SyncedPed>();
v.LockStatus=packet.LockStatus;
v.RadioStation=packet.RadioStation;
v.LicensePlate=packet.LicensePlate;
v.Livery=packet.Livery;
foreach (KeyValuePair<int, int> pair in packet.Passengers)
2022-05-22 15:55:26 +08:00
{
if (EntityPool.PedExists(pair.Value))
{
v.Passengers.Add((VehicleSeat)pair.Key, EntityPool.GetPedByID(pair.Value));
}
2022-05-22 15:55:26 +08:00
}
v.LastFullSynced= Main.Ticked;
2022-05-22 15:55:26 +08:00
}
}
private static void ProjectileSync(Packets.ProjectileSync packet)
{
var p = EntityPool.GetProjectileByID(packet.ID);
if (p==null)
{
if (packet.Exploded) { return; }
2022-07-11 11:59:32 +08:00
// Main.Logger.Debug($"Creating new projectile: {(WeaponHash)packet.WeaponHash}");
EntityPool.ThreadSafe.Add(p=new SyncedProjectile(packet.ID));
}
p.Position=packet.Position;
p.Rotation=packet.Rotation;
p.Velocity=packet.Velocity;
p.Hash=(WeaponHash)packet.WeaponHash;
p.ShooterID=packet.ShooterID;
p.Exploded=packet.Exploded;
p.LastSynced=Main.Ticked;
2022-05-22 15:55:26 +08:00
}
}
}