Files
RAGECOOP-V/Client/Scripts/Networking/Receive.cs

388 lines
16 KiB
C#
Raw Normal View History

2022-10-23 19:02:39 +08:00
using System;
using System.Threading;
using GTA;
using GTA.UI;
2022-05-22 15:55:26 +08:00
using Lidgren.Network;
using RageCoop.Client.Menus;
using RageCoop.Client.Scripting;
2022-07-20 17:50:01 +08:00
using RageCoop.Core;
2022-10-10 16:45:58 +08:00
using RageCoop.Core.Scripting;
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-13 08:22:14 +08:00
2022-07-20 17:50:01 +08:00
private static readonly AutoResetEvent _publicKeyReceived = new AutoResetEvent(false);
2022-10-23 19:02:39 +08:00
public static void ProcessMessage(NetIncomingMessage message)
2022-05-22 15:55:26 +08:00
{
2022-10-23 19:02:39 +08:00
if (message == null) return;
2022-10-19 19:07:46 +08:00
var _recycle = true;
switch (message.MessageType)
2022-05-22 15:55:26 +08:00
{
case NetIncomingMessageType.StatusChanged:
2022-10-23 19:02:39 +08:00
var status = (NetConnectionStatus)message.ReadByte();
var reason = message.ReadString();
switch (status)
{
case NetConnectionStatus.InitiatedConnect:
2022-10-23 19:02:39 +08:00
if (message.SenderConnection == ServerConnection) CoopMenu.InitiateConnectionMenuSetting();
break;
case NetConnectionStatus.Connected:
2022-09-06 21:46:35 +08:00
if (message.SenderConnection == ServerConnection)
2022-07-20 17:50:01 +08:00
{
2022-08-08 17:03:41 +08:00
var response = message.SenderConnection.RemoteHailMessage;
2022-09-06 21:46:35 +08:00
if ((PacketType)response.ReadByte() != PacketType.HandshakeSuccess)
2022-08-08 17:03:41 +08:00
throw new Exception("Invalid handshake response!");
var p = new Packets.HandshakeSuccess();
p.Deserialize(response);
2022-10-23 19:02:39 +08:00
foreach (var player in p.Players) PlayerList.SetPlayer(player.ID, player.Username);
2023-02-13 20:44:50 +08:00
Connected();
2022-08-08 17:03:41 +08:00
}
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
2022-10-23 19:02:39 +08:00
if (message.SenderConnection.RemoteHailMessage == null) return;
2022-09-06 21:46:35 +08:00
2022-08-10 20:42:47 +08:00
var p = message.SenderConnection.RemoteHailMessage.GetPacket<Packets.P2PConnect>();
2022-09-06 21:46:35 +08:00
if (PlayerList.Players.TryGetValue(p.ID, out var player))
2022-08-10 20:42:47 +08:00
{
2022-09-06 21:46:35 +08:00
player.Connection = message.SenderConnection;
2023-02-13 17:51:18 +08:00
Log.Debug($"Direct connection to {player.Username} established");
2022-08-10 20:42:47 +08:00
}
else
2022-08-08 17:03:41 +08:00
{
2023-02-13 17:51:18 +08:00
Log.Info(
2022-10-23 19:02:39 +08:00
$"Unidentified peer connection from {message.SenderEndPoint} was rejected.");
2022-08-10 20:42:47 +08:00
message.SenderConnection.Disconnect("eat poop");
}
2022-08-08 17:03:41 +08:00
}
2022-10-23 19:02:39 +08:00
break;
case NetConnectionStatus.Disconnected:
2023-02-13 20:44:50 +08:00
if (message.SenderConnection == ServerConnection) API.QueueAction(() => CleanUp(reason));
break;
}
2022-10-23 19:02:39 +08:00
break;
case NetIncomingMessageType.Data:
2022-10-23 19:02:39 +08:00
{
if (message.LengthBytes == 0) break;
var packetType = PacketType.Unknown;
try
{
2022-10-23 19:02:39 +08:00
// Get packet type
packetType = (PacketType)message.ReadByte();
switch (packetType)
2022-05-22 15:55:26 +08:00
{
2022-10-23 19:02:39 +08:00
case PacketType.Response:
2022-06-24 10:33:36 +08:00
{
2022-10-23 19:02:39 +08:00
var id = message.ReadInt32();
if (PendingResponses.TryGetValue(id, out var callback))
{
callback((PacketType)message.ReadByte(), message);
PendingResponses.Remove(id);
}
break;
2022-06-24 10:33:36 +08:00
}
2022-10-23 19:02:39 +08:00
case PacketType.Request:
{
var id = message.ReadInt32();
var realType = (PacketType)message.ReadByte();
if (RequestHandlers.TryGetValue(realType, out var handler))
{
var response = Peer.CreateMessage();
response.Write((byte)PacketType.Response);
response.Write(id);
handler(message).Pack(response);
Peer.SendMessage(response, ServerConnection, NetDeliveryMethod.ReliableOrdered,
message.SequenceChannel);
Peer.FlushSendQueue();
}
else
{
2023-02-13 17:51:18 +08:00
Log.Debug("Did not find a request handler of type: " + realType);
2022-10-23 19:02:39 +08:00
}
break;
}
default:
2022-07-20 17:50:01 +08:00
{
2022-10-23 19:02:39 +08:00
HandlePacket(packetType, message, message.SenderConnection, ref _recycle);
break;
}
2022-06-24 10:33:36 +08:00
}
}
2022-10-23 19:02:39 +08:00
catch (Exception ex)
2022-06-24 10:33:36 +08:00
{
2022-10-23 19:02:39 +08:00
API.QueueAction(() =>
2022-06-24 10:33:36 +08:00
{
2022-10-23 19:02:39 +08:00
Notification.Show($"~r~~h~Packet Error {ex.Message}");
return true;
});
2023-02-13 17:51:18 +08:00
Log.Error($"[{packetType}] {ex.Message}");
Log.Error(ex);
2022-10-23 19:02:39 +08:00
Peer.Shutdown($"Packet Error [{packetType}]");
}
2022-07-20 17:50:01 +08:00
2022-10-23 19:02:39 +08:00
break;
}
case NetIncomingMessageType.UnconnectedData:
{
var packetType = (PacketType)message.ReadByte();
switch (packetType)
{
case PacketType.HolePunch:
{
HolePunch.Punched(message.GetPacket<Packets.HolePunch>(), message.SenderEndPoint);
break;
}
case PacketType.PublicKeyResponse:
{
if (message.SenderEndPoint.ToString() != _targetServerEP.ToString() || !IsConnecting) break;
var packet = message.GetPacket<Packets.PublicKeyResponse>();
Security.SetServerPublicKey(packet.Modulus, packet.Exponent);
_publicKeyReceived.Set();
break;
2022-08-10 20:42:47 +08:00
}
2022-06-24 10:33:36 +08:00
}
2022-10-23 19:02:39 +08:00
break;
}
case NetIncomingMessageType.DebugMessage:
case NetIncomingMessageType.ErrorMessage:
case NetIncomingMessageType.WarningMessage:
case NetIncomingMessageType.VerboseDebugMessage:
2023-02-13 17:51:18 +08:00
Log.Trace(message.ReadString());
break;
}
2022-10-23 19:02:39 +08:00
if (_recycle) Peer.Recycle(message);
2022-05-22 15:55:26 +08:00
}
2022-10-23 19:02:39 +08:00
private static void HandlePacket(PacketType packetType, NetIncomingMessage msg, NetConnection senderConnection,
ref bool recycle)
2022-07-01 12:22:31 +08:00
{
switch (packetType)
{
2022-08-10 20:42:47 +08:00
case PacketType.HolePunchInit:
HolePunch.Add(msg.GetPacket<Packets.HolePunchInit>());
2022-07-01 12:22:31 +08:00
break;
2022-08-10 20:42:47 +08:00
case PacketType.PlayerConnect:
PlayerConnect(msg.GetPacket<Packets.PlayerConnect>());
2022-07-01 12:22:31 +08:00
break;
2022-08-10 20:42:47 +08:00
case PacketType.PlayerDisconnect:
PlayerDisconnect(msg.GetPacket<Packets.PlayerDisconnect>());
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.PlayerInfoUpdate:
PlayerList.UpdatePlayer(msg.GetPacket<Packets.PlayerInfoUpdate>());
2022-07-01 12:22:31 +08:00
break;
2022-08-10 20:42:47 +08:00
case PacketType.VehicleSync:
ReceivedPackets.VehicelPacket.Deserialize(msg);
2022-08-13 08:22:14 +08:00
VehicleSync(ReceivedPackets.VehicelPacket);
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:
ReceivedPackets.PedPacket.Deserialize(msg);
2022-08-13 08:22:14 +08:00
PedSync(ReceivedPackets.PedPacket);
2022-07-01 12:22:31 +08:00
break;
case PacketType.ProjectileSync:
ReceivedPackets.ProjectilePacket.Deserialize(msg);
2022-08-13 08:22:14 +08:00
ProjectileSync(ReceivedPackets.ProjectilePacket);
2022-08-10 20:42:47 +08:00
break;
2022-07-01 12:22:31 +08:00
case PacketType.ChatMessage:
2022-10-23 19:02:39 +08:00
{
var packet = new Packets.ChatMessage(b => Security.Decrypt(b));
packet.Deserialize(msg);
2022-07-01 12:22:31 +08:00
2022-10-23 19:02:39 +08:00
API.QueueAction(() =>
{
2023-02-13 20:44:50 +08:00
MainChat.AddMessage(packet.Username, packet.Message);
2022-10-23 19:02:39 +08:00
return true;
});
}
2022-07-01 12:22:31 +08:00
break;
2022-08-10 20:42:47 +08:00
2022-08-13 02:19:40 +02:00
case PacketType.Voice:
2022-10-23 19:02:39 +08:00
{
2023-02-13 20:44:50 +08:00
if (Settings.Voice)
2022-08-13 02:19:40 +02:00
{
2022-10-23 19:02:39 +08:00
var packet = new Packets.Voice();
packet.Deserialize(msg);
2022-08-13 03:39:11 +02:00
2022-08-14 23:35:36 +02:00
2022-10-23 19:02:39 +08:00
var player = EntityPool.GetPedByID(packet.ID);
player.IsSpeaking = true;
2023-02-13 20:44:50 +08:00
player.LastSpeakingTime = Ticked;
2022-08-15 16:13:53 +08:00
2022-10-23 19:02:39 +08:00
Voice.AddVoiceData(packet.Buffer, packet.Recorded);
2022-08-13 02:19:40 +02:00
}
2022-10-23 19:02:39 +08:00
}
2022-08-13 02:19:40 +02:00
break;
2022-07-01 12:22:31 +08:00
case PacketType.CustomEvent:
2022-10-23 19:02:39 +08:00
{
var packet = new Packets.CustomEvent();
if (((CustomEventFlags)msg.PeekByte()).HasEventFlag(CustomEventFlags.Queued))
2022-07-01 12:22:31 +08:00
{
2022-10-23 19:02:39 +08:00
recycle = false;
API.QueueAction(() =>
2022-07-05 11:18:26 +08:00
{
2022-10-10 16:45:58 +08:00
packet.Deserialize(msg);
2022-10-23 19:02:39 +08:00
API.Events.InvokeCustomEventReceived(packet);
Peer.Recycle(msg);
});
2022-07-05 11:18:26 +08:00
}
2022-10-23 19:02:39 +08:00
else
2022-07-01 12:22:31 +08:00
{
packet.Deserialize(msg);
2022-10-23 19:02:39 +08:00
API.Events.InvokeCustomEventReceived(packet);
2022-07-01 12:22:31 +08:00
}
2022-10-23 19:02:39 +08:00
}
break;
case PacketType.FileTransferChunk:
{
var packet = new Packets.FileTransferChunk();
packet.Deserialize(msg);
DownloadManager.Write(packet.ID, packet.FileChunk);
}
2022-07-01 12:22:31 +08:00
break;
2022-08-10 20:42:47 +08:00
2022-07-01 12:22:31 +08:00
default:
if (packetType.IsSyncEvent())
{
recycle = false;
2022-08-10 20:42:47 +08:00
// Dispatch to script thread
2022-10-23 19:02:39 +08:00
API.QueueAction(() =>
{
SyncEvents.HandleEvent(packetType, msg);
return true;
});
2022-07-01 12:22:31 +08:00
}
2022-10-23 19:02:39 +08:00
2022-07-01 12:22:31 +08:00
break;
}
}
private static void PedSync(Packets.PedSync packet)
2022-05-22 15:55:26 +08:00
{
2022-10-23 19:02:39 +08:00
var c = EntityPool.GetPedByID(packet.ID);
2022-09-06 21:46:35 +08:00
if (c == null)
2023-02-13 17:51:18 +08:00
// Log.Debug($"Creating character for incoming sync:{packet.ID}");
2022-09-06 21:46:35 +08:00
EntityPool.ThreadSafe.Add(c = new SyncedPed(packet.ID));
2022-10-23 19:02:39 +08:00
var flags = packet.Flags;
2022-09-06 21:46:35 +08:00
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-09-06 21:46:35 +08:00
c.Flags = packet.Flags;
c.Heading = packet.Heading;
2022-07-17 18:44:16 +08:00
c.Position = packet.Position;
if (c.IsRagdoll)
{
2022-09-06 21:46:35 +08:00
c.HeadPosition = packet.HeadPosition;
c.RightFootPosition = packet.RightFootPosition;
c.LeftFootPosition = packet.LeftFootPosition;
2022-07-17 18:44:16 +08:00
}
2022-09-06 21:46:35 +08:00
else if (c.Speed >= 4)
{
2022-09-06 21:46:35 +08:00
c.VehicleID = packet.VehicleID;
c.Seat = packet.Seat;
}
2022-10-23 19:02:39 +08:00
if (c.IsAiming) c.AimCoords = packet.AimCoords;
bool full = packet.Flags.HasPedFlag(PedDataFlags.IsFullSync);
if (full)
{
if (packet.Speed == 4)
c.VehicleWeapon = packet.VehicleWeapon;
c.CurrentWeapon = packet.CurrentWeapon;
2022-09-06 21:46:35 +08:00
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;
2022-05-22 15:55:26 +08:00
}
c.SetLastSynced(full);
2022-05-22 15:55:26 +08:00
}
2022-10-23 19:02:39 +08:00
private static void VehicleSync(Packets.VehicleSync packet)
2022-05-22 15:55:26 +08:00
{
2022-10-23 19:02:39 +08:00
var v = EntityPool.GetVehicleByID(packet.ID);
if (v == null) EntityPool.ThreadSafe.Add(v = new SyncedVehicle(packet.ID));
if (v.IsLocal) return;
2022-09-06 21:46:35 +08:00
v.ID = packet.ID;
v.OwnerID = packet.OwnerID;
v.Flags = packet.Flags;
v.Position = packet.Position;
v.LastQuaternion = v.Quaternion;
2022-09-06 21:46:35 +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;
bool full = packet.Flags.HasVehFlag(VehicleDataFlags.IsFullSync);
if (full)
{
2022-09-06 21:46:35 +08:00
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.LockStatus = packet.LockStatus;
v.RadioStation = packet.RadioStation;
v.LicensePlate = packet.LicensePlate;
v.Livery = packet.Livery;
2022-05-22 15:55:26 +08:00
}
v.SetLastSynced(full);
}
2022-10-23 19:02:39 +08:00
private static void ProjectileSync(Packets.ProjectileSync packet)
{
var p = EntityPool.GetProjectileByID(packet.ID);
2022-09-06 21:46:35 +08:00
if (p == null)
{
2022-10-23 19:02:39 +08:00
if (packet.Flags.HasProjDataFlag(ProjectileDataFlags.Exploded)) return;
2023-02-13 17:51:18 +08:00
// Log.Debug($"Creating new projectile: {(WeaponHash)packet.WeaponHash}");
2022-09-06 21:46:35 +08:00
EntityPool.ThreadSafe.Add(p = new SyncedProjectile(packet.ID));
}
2022-10-23 19:02:39 +08:00
2022-09-06 21:46:35 +08:00
p.Flags = packet.Flags;
p.Position = packet.Position;
p.Rotation = packet.Rotation;
p.Velocity = packet.Velocity;
p.WeaponHash = (WeaponHash)packet.WeaponHash;
2022-10-23 19:02:39 +08:00
p.Shooter = packet.Flags.HasProjDataFlag(ProjectileDataFlags.IsShotByVehicle)
? (SyncedEntity)EntityPool.GetVehicleByID(packet.ShooterID)
: EntityPool.GetPedByID(packet.ShooterID);
p.SetLastSynced(false);
2022-05-22 15:55:26 +08:00
}
2022-10-23 19:02:39 +08:00
/// <summary>
/// Reduce GC pressure by reusing frequently used packets
/// </summary>
private static class ReceivedPackets
{
public static readonly Packets.PedSync PedPacket = new Packets.PedSync();
public static readonly Packets.VehicleSync VehicelPacket = new Packets.VehicleSync();
public static readonly Packets.ProjectileSync ProjectilePacket = new Packets.ProjectileSync();
}
2022-05-22 15:55:26 +08:00
}
2022-10-23 19:02:39 +08:00
}