Rewrote packet system to reduce heap allocation

This commit is contained in:
sardelka9515
2022-09-08 12:37:06 -07:00
parent f1fc96bbd7
commit 76c529f1d1
29 changed files with 627 additions and 679 deletions

View File

@ -107,24 +107,9 @@ namespace RageCoop.Client
private bool _lastDead;
private void OnTick(object sender, EventArgs e)
{
/*
unsafe
{
var stationName = Function.Call<string>(Hash.GET_RADIO_STATION_NAME, Game.RadioStation);
//_GET_CURRENT_RADIO_TRACK_NAME
var currentTrack = Function.Call<int>((Hash)0x34D66BC058019CE0, stationName);
Function.Call(Hash.SET_RADIO_TRACK, "RADIO_03_HIPHOP_NEW", "ARM1_RADIO_STARTS");
return currentTrack;
var h1 = Function.Call<int>(Hash._GET_CURRENT_RADIO_STATION_HASH);
return $"{h1},{h2},{s},{s1}";
}
*/
P = Game.Player.Character;
PlayerPosition = P.ReadPosition();
FPS = Game.FPS;
// World.DrawMarker(MarkerType.DebugSphere, PedExtensions.RaycastEverything(default), default, default, new Vector3(0.2f, 0.2f, 0.2f), Color.AliceBlue);
if (Game.IsLoading)
{
return;

View File

@ -17,8 +17,8 @@ namespace RageCoop.Client
public static bool ShowNetworkInfo = false;
public static Security Security;
public static NetConnection ServerConnection;
private static readonly Dictionary<int, Action<PacketType, byte[]>> PendingResponses = new Dictionary<int, Action<PacketType, byte[]>>();
internal static readonly Dictionary<PacketType, Func<byte[], Packet>> RequestHandlers = new Dictionary<PacketType, Func<byte[], Packet>>();
private static readonly Dictionary<int, Action<PacketType, NetIncomingMessage>> PendingResponses = new Dictionary<int, Action<PacketType, NetIncomingMessage>>();
internal static readonly Dictionary<PacketType, Func<NetIncomingMessage, Packet>> RequestHandlers = new Dictionary<PacketType, Func<NetIncomingMessage, Packet>>();
internal static float SimulatedLatency = 0;
public static bool IsConnecting { get; private set; }
public static IPEndPoint _targetServerEP;
@ -89,6 +89,8 @@ namespace RageCoop.Client
try
{
_targetServerEP = CoreUtils.StringToEndPoint(address);
// Ensure static constructor invocation
DownloadManager.Cleanup();
Peer = new CoopPeer(config);
Peer.OnMessageReceived += (s, m) =>

View File

@ -23,7 +23,7 @@ namespace RageCoop.Client
/// <summary>
/// Used to reslove entity handle in a <see cref="Packets.CustomEvent"/>
/// </summary>
private static readonly Func<byte, BitReader, object> _resolveHandle = (t, reader) =>
private static readonly Func<byte, NetIncomingMessage, object> _resolveHandle = (t, reader) =>
{
switch (t)
{
@ -40,10 +40,11 @@ namespace RageCoop.Client
}
};
private static readonly AutoResetEvent _publicKeyReceived = new AutoResetEvent(false);
private static bool _recycle;
public static void ProcessMessage(NetIncomingMessage message)
{
if (message == null) { return; }
_recycle = true;
switch (message.MessageType)
{
case NetIncomingMessageType.StatusChanged:
@ -66,7 +67,7 @@ namespace RageCoop.Client
throw new Exception("Invalid handshake response!");
}
var p = new Packets.HandshakeSuccess();
p.Deserialize(response.ReadBytes(response.ReadInt32()));
p.Deserialize(response);
foreach (var player in p.Players)
{
PlayerList.SetPlayer(player.ID, player.Username);
@ -114,7 +115,7 @@ namespace RageCoop.Client
int id = message.ReadInt32();
if (PendingResponses.TryGetValue(id, out var callback))
{
callback((PacketType)message.ReadByte(), message.ReadBytes(message.ReadInt32()));
callback((PacketType)message.ReadByte(), message);
PendingResponses.Remove(id);
}
break;
@ -123,23 +124,25 @@ namespace RageCoop.Client
{
int id = message.ReadInt32();
var realType = (PacketType)message.ReadByte();
int len = message.ReadInt32();
if (RequestHandlers.TryGetValue(realType, out var handler))
{
var response = Peer.CreateMessage();
response.Write((byte)PacketType.Response);
response.Write(id);
handler(message.ReadBytes(len)).Pack(response);
handler(message).Pack(response);
Peer.SendMessage(response, ServerConnection, NetDeliveryMethod.ReliableOrdered, message.SequenceChannel);
Peer.FlushSendQueue();
}
else
{
Main.Logger.Debug("Did not find a request handler of type: " + realType);
}
break;
}
default:
{
byte[] data = message.ReadBytes(message.ReadInt32());
HandlePacket(packetType, data, message.SenderConnection);
HandlePacket(packetType, message, message.SenderConnection,ref _recycle);
break;
}
}
@ -148,7 +151,7 @@ namespace RageCoop.Client
{
Main.QueueAction(() =>
{
GTA.UI.Notification.Show("~r~~h~Packet Error");
GTA.UI.Notification.Show($"~r~~h~Packet Error {ex.Message}");
return true;
});
Main.Logger.Error($"[{packetType}] {ex.Message}");
@ -160,20 +163,18 @@ namespace RageCoop.Client
case NetIncomingMessageType.UnconnectedData:
{
var packetType = (PacketType)message.ReadByte();
int len = message.ReadInt32();
byte[] data = message.ReadBytes(len);
switch (packetType)
{
case PacketType.HolePunch:
{
HolePunch.Punched(data.GetPacket<Packets.HolePunch>(), message.SenderEndPoint);
HolePunch.Punched(message.GetPacket<Packets.HolePunch>(), message.SenderEndPoint);
break;
}
case PacketType.PublicKeyResponse:
{
if (message.SenderEndPoint.ToString() != _targetServerEP.ToString() || !IsConnecting) { break; }
var packet = data.GetPacket<Packets.PublicKeyResponse>();
var packet = message.GetPacket<Packets.PublicKeyResponse>();
Security.SetServerPublicKey(packet.Modulus, packet.Exponent);
_publicKeyReceived.Set();
break;
@ -190,41 +191,42 @@ namespace RageCoop.Client
default:
break;
}
Peer.Recycle(message);
if (_recycle)
{
Peer.Recycle(message);
}
}
private static void HandlePacket(PacketType packetType, byte[] data, NetConnection senderConnection)
private static void HandlePacket(PacketType packetType, NetIncomingMessage msg, NetConnection senderConnection, ref bool recycle)
{
switch (packetType)
{
case PacketType.HolePunchInit:
HolePunch.Add(data.GetPacket<Packets.HolePunchInit>());
HolePunch.Add(msg.GetPacket<Packets.HolePunchInit>());
break;
case PacketType.PlayerConnect:
PlayerConnect(data.GetPacket<Packets.PlayerConnect>());
PlayerConnect(msg.GetPacket<Packets.PlayerConnect>());
break;
case PacketType.PlayerDisconnect:
PlayerDisconnect(data.GetPacket<Packets.PlayerDisconnect>());
PlayerDisconnect(msg.GetPacket<Packets.PlayerDisconnect>());
break;
case PacketType.PlayerInfoUpdate:
PlayerList.UpdatePlayer(data.GetPacket<Packets.PlayerInfoUpdate>());
PlayerList.UpdatePlayer(msg.GetPacket<Packets.PlayerInfoUpdate>());
break;
case PacketType.VehicleSync:
ReceivedPackets.VehicelPacket.Deserialize(data);
ReceivedPackets.VehicelPacket.Deserialize(msg);
VehicleSync(ReceivedPackets.VehicelPacket);
break;
case PacketType.PedSync:
ReceivedPackets.PedPacket.Deserialize(data);
ReceivedPackets.PedPacket.Deserialize(msg);
PedSync(ReceivedPackets.PedPacket);
break;
case PacketType.ProjectileSync:
ReceivedPackets.ProjectilePacket.Deserialize(data);
ReceivedPackets.ProjectilePacket.Deserialize(msg);
ProjectileSync(ReceivedPackets.ProjectilePacket);
break;
@ -232,7 +234,7 @@ namespace RageCoop.Client
{
Packets.ChatMessage packet = new Packets.ChatMessage((b) => Security.Decrypt(b));
packet.Deserialize(data);
packet.Deserialize(msg);
Main.QueueAction(() => { Main.MainChat.AddMessage(packet.Username, packet.Message); return true; });
}
@ -243,7 +245,7 @@ namespace RageCoop.Client
if (Main.Settings.Voice)
{
Packets.Voice packet = new Packets.Voice();
packet.Deserialize(data);
packet.Deserialize(msg);
SyncedPed player = EntityPool.GetPedByID(packet.ID);
@ -258,18 +260,20 @@ namespace RageCoop.Client
case PacketType.CustomEvent:
{
Packets.CustomEvent packet = new Packets.CustomEvent(_resolveHandle);
packet.Deserialize(data);
packet.Deserialize(msg);
Scripting.API.Events.InvokeCustomEventReceived(packet);
}
break;
case PacketType.CustomEventQueued:
{
recycle = false;
Packets.CustomEvent packet = new Packets.CustomEvent(_resolveHandle);
Main.QueueAction(() =>
{
packet.Deserialize(data);
packet.Deserialize(msg);
Scripting.API.Events.InvokeCustomEventReceived(packet);
Peer.Recycle(msg);
});
}
break;
@ -277,7 +281,7 @@ namespace RageCoop.Client
case PacketType.FileTransferChunk:
{
Packets.FileTransferChunk packet = new Packets.FileTransferChunk();
packet.Deserialize(data);
packet.Deserialize(msg);
DownloadManager.Write(packet.ID, packet.FileChunk);
}
break;
@ -285,8 +289,9 @@ namespace RageCoop.Client
default:
if (packetType.IsSyncEvent())
{
recycle = false;
// Dispatch to script thread
Main.QueueAction(() => { SyncEvents.HandleEvent(packetType, data); return true; });
Main.QueueAction(() => { SyncEvents.HandleEvent(packetType, msg); Peer.Recycle(msg); return true; });
}
break;
}

View File

@ -16,7 +16,7 @@ using System.Resources;
// Version informationr(
[assembly: AssemblyVersion("1.5.3.176")]
[assembly: AssemblyFileVersion("1.5.3.176")]
[assembly: AssemblyVersion("1.5.3.188")]
[assembly: AssemblyFileVersion("1.5.3.188")]
[assembly: NeutralResourcesLanguageAttribute( "en-US" )]

View File

@ -159,44 +159,39 @@ namespace RageCoop.Client
WeaponUtil.GetFlashFX((WeaponHash)p.WeaponHash),
b.Position, b.ForwardVector.ToEulerRotation(v.Bones[35].UpVector), 1);
}
public static void HandleEvent(PacketType type, byte[] data)
public static void HandleEvent(PacketType type,NetIncomingMessage msg)
{
switch (type)
{
case PacketType.BulletShot:
{
Packets.BulletShot p = new Packets.BulletShot();
p.Deserialize(data);
p.Deserialize(msg);
HandleBulletShot(p.StartPosition, p.EndPosition, p.WeaponHash, p.OwnerID);
break;
}
case PacketType.VehicleBulletShot:
{
HandleVehicleBulletShot(data.GetPacket<Packets.VehicleBulletShot>());
HandleVehicleBulletShot(msg.GetPacket<Packets.VehicleBulletShot>());
break;
}
case PacketType.OwnerChanged:
{
Packets.OwnerChanged packet = new Packets.OwnerChanged();
packet.Deserialize(data);
HandleOwnerChanged(packet);
HandleOwnerChanged(msg.GetPacket<Packets.OwnerChanged>());
}
break;
case PacketType.PedKilled:
{
var packet = new Packets.PedKilled();
packet.Deserialize(data);
HandlePedKilled(packet);
HandlePedKilled(msg.GetPacket<Packets.PedKilled>());
}
break;
case PacketType.NozzleTransform:
{
var packet = new Packets.NozzleTransform();
packet.Deserialize(data);
HandleNozzleTransform(packet);
HandleNozzleTransform(msg.GetPacket<Packets.NozzleTransform>());
break;
}
}
Networking.Peer.Recycle(msg);
}
#endregion

View File

@ -14,6 +14,7 @@ using Lidgren.Network;
using Newtonsoft.Json;
using System.Runtime.InteropServices;
using System.Net.NetworkInformation;
using Newtonsoft.Json.Linq;
[assembly: InternalsVisibleTo("RageCoop.Server")]
[assembly: InternalsVisibleTo("RageCoop.Client")]
@ -35,45 +36,44 @@ namespace RageCoop.Core
{
return ToIgnore.Contains(name);
}
public static (byte, byte[]) GetBytesFromObject(object obj)
public static void GetBytesFromObject(object obj,NetOutgoingMessage m)
{
switch (obj)
{
case byte value:
return (0x01, new byte[] { value });
m.Write((byte)0x01);m.Write(value);break;
case short value:
return (0x02, BitConverter.GetBytes(value));
m.Write((byte)0x02); m.Write(value); break;
case ushort value:
return (0x03, BitConverter.GetBytes(value));
m.Write((byte)0x03); m.Write(value); break;
case int value:
return (0x04, BitConverter.GetBytes(value));
m.Write((byte)0x04); m.Write(value); break;
case uint value:
return (0x05, BitConverter.GetBytes(value));
m.Write((byte)0x05); m.Write(value); break;
case long value:
return (0x06, BitConverter.GetBytes(value));
m.Write((byte)0x06); m.Write(value); break;
case ulong value:
return (0x07, BitConverter.GetBytes(value));
m.Write((byte)0x07); m.Write(value); break;
case float value:
return (0x08, BitConverter.GetBytes(value));
m.Write((byte)0x08); m.Write(value); break;
case bool value:
return (0x09, BitConverter.GetBytes(value));
m.Write((byte)0x09); m.Write(value); break;
case string value:
return (0x10, value.GetBytesWithLength());
m.Write((byte)0x10); m.Write(value); break;
case Vector3 value:
return (0x11, value.GetBytes());
m.Write((byte)0x11); m.Write(value); break;
case Quaternion value:
return (0x12, value.GetBytes());
m.Write((byte)0x12); m.Write(value); break;
case GTA.Model value:
return (0x13, BitConverter.GetBytes(value));
m.Write((byte)0x13); m.Write(value); break;
case Vector2 value:
return (0x14, value.GetBytes());
m.Write((byte)0x14); m.Write(value); break;
case byte[] value:
return (0x15, value);
case Tuple<byte, byte[]> _:
var tup = (Tuple<byte, byte[]>)obj;
return (tup.Item1, tup.Item2);
m.Write((byte)0x15); m.WriteByteArray(value); break;
case Tuple<byte, byte[]> value:
m.Write(value.Item1); m.Write(value.Item2); break;
default:
return (0x0, null);
throw new Exception("Unsupported object type: " + obj.GetType());
}
}
public static IPEndPoint StringToEndPoint(string endpointstring)
@ -239,62 +239,6 @@ namespace RageCoop.Core
}
internal static class Extensions
{
public static void AddVector3(this List<byte> bytes, Vector3 vec3)
{
bytes.AddRange(BitConverter.GetBytes(vec3.X));
bytes.AddRange(BitConverter.GetBytes(vec3.Y));
bytes.AddRange(BitConverter.GetBytes(vec3.Z));
}
public static void AddQuaternion(this List<byte> bytes, Quaternion quat)
{
bytes.AddRange(BitConverter.GetBytes(quat.X));
bytes.AddRange(BitConverter.GetBytes(quat.Y));
bytes.AddRange(BitConverter.GetBytes(quat.Z));
bytes.AddRange(BitConverter.GetBytes(quat.W));
}
public static void AddInt(this List<byte> bytes,int i)
{
bytes.AddRange(BitConverter.GetBytes(i));
}
public static void AddUint(this List<byte> bytes, uint i)
{
bytes.AddRange(BitConverter.GetBytes(i));
}
public static void AddShort(this List<byte> bytes, short i)
{
bytes.AddRange(BitConverter.GetBytes(i));
}
public static void AddUshort(this List<byte> bytes, ushort i)
{
bytes.AddRange(BitConverter.GetBytes(i));
}
public static void AddLong(this List<byte> bytes, long i)
{
bytes.AddRange(BitConverter.GetBytes(i));
}
public static void AddUlong(this List<byte> bytes, ulong i)
{
bytes.AddRange(BitConverter.GetBytes(i));
}
public static void AddFloat(this List<byte> bytes, float i)
{
bytes.AddRange(BitConverter.GetBytes(i));
}
public static void AddBool(this List<byte> bytes, bool b)
{
bytes.Add(b? (byte)1 :(byte)0);
}
public static void AddString(this List<byte> bytes, string s)
{
var sb = Encoding.UTF8.GetBytes(s);
bytes.AddInt(sb.Length);
bytes.AddRange(sb);
}
public static void AddArray(this List<byte> bytes, byte[] toadd)
{
bytes.AddInt(toadd.Length);
bytes.AddRange(toadd);
}
public static byte[] GetBytes(this string s)
{
return Encoding.UTF8.GetBytes(s);
@ -333,17 +277,10 @@ namespace RageCoop.Core
// 16 bytes
return new List<byte[]>() { BitConverter.GetBytes(qua.X), BitConverter.GetBytes(qua.Y), BitConverter.GetBytes(qua.Z), BitConverter.GetBytes(qua.W) }.Join(4);
}
public static T GetPacket<T>(this NetIncomingMessage msg, T existingPacket = null) where T : Packet, new()
public static T GetPacket<T>(this NetIncomingMessage msg) where T: Packet, new()
{
msg.ReadByte();
return GetPacket<T>(msg.ReadBytes(msg.ReadInt32()),existingPacket);
}
public static T GetPacket<T>(this byte[] data, T existingPacket=null) where T : Packet, new()
{
var p = existingPacket??new T();
p.Deserialize(data);
var p = new T();
p.Deserialize(msg);
return p;
}
public static bool HasPedFlag(this PedDataFlags flagToCheck, PedDataFlags flag)

View File

@ -0,0 +1,130 @@
using System;
using System.Collections.Generic;
using System.Text;
using GTA.Math;
using Lidgren.Network;
namespace RageCoop.Core
{
internal static class PacketExtensions
{
#region MESSAGE-READ
public static Vector3 ReadVector3(this NetIncomingMessage m)
{
return new Vector3
{
X = m.ReadFloat(),
Y = m.ReadFloat(),
Z = m.ReadFloat(),
};
}
public static Vector2 ReadVector2(this NetIncomingMessage m)
{
return new Vector2
{
X = m.ReadFloat(),
Y = m.ReadFloat(),
};
}
public static Quaternion ReadQuaternion(this NetIncomingMessage m)
{
return new Quaternion
{
X = m.ReadFloat(),
Y = m.ReadFloat(),
Z = m.ReadFloat(),
W = m.ReadFloat(),
};
}
public static byte[] ReadByteArray(this NetIncomingMessage m)
{
return m.ReadBytes(m.ReadInt32());
}
#endregion
#region MESSAGE-WRITE
public static void Write(this NetOutgoingMessage m,Vector3 v)
{
m.Write(v.X);
m.Write(v.Y);
m.Write(v.Z);
}
public static void Write(this NetOutgoingMessage m, Quaternion q)
{
m.Write(q.X);
m.Write(q.Y);
m.Write(q.Z);
m.Write(q.W);
}
public static void WriteByteArray(this NetOutgoingMessage m, byte[] b)
{
m.Write(b.Length);
m.Write(b);
}
#endregion
#region BYTE-LIST
public static void AddVector3(this List<byte> bytes, Vector3 vec3)
{
bytes.AddRange(BitConverter.GetBytes(vec3.X));
bytes.AddRange(BitConverter.GetBytes(vec3.Y));
bytes.AddRange(BitConverter.GetBytes(vec3.Z));
}
public static void AddQuaternion(this List<byte> bytes, Quaternion quat)
{
bytes.AddRange(BitConverter.GetBytes(quat.X));
bytes.AddRange(BitConverter.GetBytes(quat.Y));
bytes.AddRange(BitConverter.GetBytes(quat.Z));
bytes.AddRange(BitConverter.GetBytes(quat.W));
}
public static void AddInt(this List<byte> bytes, int i)
{
bytes.AddRange(BitConverter.GetBytes(i));
}
public static void AddUint(this List<byte> bytes, uint i)
{
bytes.AddRange(BitConverter.GetBytes(i));
}
public static void AddShort(this List<byte> bytes, short i)
{
bytes.AddRange(BitConverter.GetBytes(i));
}
public static void AddUshort(this List<byte> bytes, ushort i)
{
bytes.AddRange(BitConverter.GetBytes(i));
}
public static void AddLong(this List<byte> bytes, long i)
{
bytes.AddRange(BitConverter.GetBytes(i));
}
public static void AddUlong(this List<byte> bytes, ulong i)
{
bytes.AddRange(BitConverter.GetBytes(i));
}
public static void AddFloat(this List<byte> bytes, float i)
{
bytes.AddRange(BitConverter.GetBytes(i));
}
public static void AddBool(this List<byte> bytes, bool b)
{
bytes.Add(b ? (byte)1 : (byte)0);
}
public static void AddString(this List<byte> bytes, string s)
{
var sb = Encoding.UTF8.GetBytes(s);
bytes.AddInt(sb.Length);
bytes.AddRange(sb);
}
public static void AddArray(this List<byte> bytes, byte[] toadd)
{
bytes.AddInt(toadd.Length);
bytes.AddRange(toadd);
}
#endregion
internal static bool IsSyncEvent(this PacketType p)
{
return (30 <= (byte)p) && ((byte)p <= 40);
}
}
}

View File

@ -25,33 +25,31 @@ namespace RageCoop.Core
public string Message { get; set; }
public override byte[] Serialize()
protected override void Serialize(NetOutgoingMessage m)
{
List<byte> byteArray = new List<byte>();
// Write Username
byteArray.AddString(Username);
m.Write(Username);
// Write Message
byteArray.AddArray(crypt(Message));
return byteArray.ToArray();
m.WriteByteArray(crypt(Message));
}
public override void Deserialize(byte[] array)
public override void Deserialize(NetIncomingMessage m)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
// Read username
Username = reader.ReadString();
Username = m.ReadString();
Message = decrypt(reader.ReadByteArray()).GetString();
Message = decrypt(m.ReadByteArray()).GetString();
#endregion
}
}

View File

@ -10,85 +10,78 @@ namespace RageCoop.Core
internal class CustomEvent : Packet
{
public override PacketType Type => (_queued ? PacketType.CustomEventQueued : PacketType.CustomEvent);
public CustomEvent(Func<byte,BitReader,object> onResolve = null,bool queued=false)
public CustomEvent(Func<byte,NetIncomingMessage,object> onResolve = null,bool queued=false)
{
_resolve= onResolve;
_queued= queued;
}
private bool _queued;
private Func<byte, BitReader, object> _resolve { get; set; }
private Func<byte, NetIncomingMessage, object> _resolve { get; set; }
public int Hash { get; set; }
public object[] Args { get; set; }
public override byte[] Serialize()
protected override void Serialize(NetOutgoingMessage m)
{
Args= Args ?? new object[] { };
List<byte> result = new List<byte>();
result.AddInt(Hash);
result.AddInt(Args.Length);
(byte, byte[]) tup;
m.Write(Hash);
m.Write(Args.Length);
foreach (var arg in Args)
{
tup=CoreUtils.GetBytesFromObject(arg);
if (tup.Item1==0||tup.Item2==null)
{
throw new ArgumentException($"Object of type {arg.GetType()} is not supported");
}
result.Add(tup.Item1);
result.AddRange(tup.Item2);
CoreUtils.GetBytesFromObject(arg,m);
}
return result.ToArray();
}
public override void Deserialize(byte[] array)
public override void Deserialize(NetIncomingMessage m)
{
BitReader reader = new BitReader(array);
Hash = reader.ReadInt32();
var len=reader.ReadInt32();
Hash = m.ReadInt32();
var len=m.ReadInt32();
Args=new object[len];
for (int i = 0; i < len; i++)
{
byte type = reader.ReadByte();
byte type = m.ReadByte();
switch (type)
{
case 0x01:
Args[i]=reader.ReadByte(); break;
Args[i]=m.ReadByte(); break;
case 0x02:
Args[i]=reader.ReadInt32(); break;
Args[i]=m.ReadInt32(); break;
case 0x03:
Args[i]=reader.ReadUInt16(); break;
Args[i]=m.ReadUInt16(); break;
case 0x04:
Args[i]=reader.ReadInt32(); break;
Args[i]=m.ReadInt32(); break;
case 0x05:
Args[i]=reader.ReadUInt32(); break;
Args[i]=m.ReadUInt32(); break;
case 0x06:
Args[i]=reader.ReadInt64(); break;
Args[i]=m.ReadInt64(); break;
case 0x07:
Args[i]=reader.ReadUInt64(); break;
Args[i]=m.ReadUInt64(); break;
case 0x08:
Args[i]=reader.ReadSingle(); break;
Args[i]=m.ReadFloat(); break;
case 0x09:
Args[i]=reader.ReadBoolean(); break;
Args[i]=m.ReadBoolean(); break;
case 0x10:
Args[i]=reader.ReadString(); break;
Args[i]=m.ReadString(); break;
case 0x11:
Args[i]=reader.ReadVector3(); break;
Args[i]=m.ReadVector3(); break;
case 0x12:
Args[i]=reader.ReadQuaternion(); break;
Args[i]=m.ReadQuaternion(); break;
case 0x13:
Args[i]=(GTA.Model)reader.ReadInt32(); break;
Args[i]=(GTA.Model)m.ReadInt32(); break;
case 0x14:
Args[i]=reader.ReadVector2(); break;
Args[i]=m.ReadVector2(); break;
case 0x15:
Args[i] = m.ReadByteArray(); break;
default:
if (_resolve==null)
{
throw new InvalidOperationException($"Unexpected type:{type}\r\n{array.Dump()}");
throw new InvalidOperationException($"Unexpected type: {type}");
}
else
{
Args[i]=_resolve(type, reader); break;
Args[i]=_resolve(type, m); break;
}
}
}

View File

@ -25,34 +25,30 @@ namespace RageCoop.Core
public long FileLength { get; set; }
public override byte[] Serialize()
protected override void Serialize(NetOutgoingMessage m)
{
List<byte> byteArray = new List<byte>();
// The ID from the download
byteArray.AddInt(ID);
m.Write(ID);
// The name of the file
byte[] nameBytes = Encoding.UTF8.GetBytes(Name);
byteArray.AddRange(BitConverter.GetBytes(nameBytes.Length));
byteArray.AddRange(nameBytes);
m.Write(Name);
// The length of the file
byteArray.AddRange(BitConverter.GetBytes(FileLength));
return byteArray.ToArray();
m.Write(FileLength);
}
public override void Deserialize(byte[] array)
public override void Deserialize(NetIncomingMessage m)
{
BitReader reader = new BitReader(array);
ID = reader.ReadInt32();
Name = reader.ReadString();
FileLength = reader.ReadInt64();
ID = m.ReadInt32();
Name = m.ReadString();
FileLength = m.ReadInt64();
}
}
@ -61,25 +57,21 @@ namespace RageCoop.Core
public override PacketType Type => PacketType.FileTransferResponse;
public int ID { get; set; }
public FileResponse Response { get; set; }
public override byte[] Serialize()
protected override void Serialize(NetOutgoingMessage m)
{
List<byte> byteArray = new List<byte>();
// The ID from the download
byteArray.AddInt(ID);
m.Write(ID);
byteArray.Add((byte)Response);
m.Write((byte)Response);
return byteArray.ToArray();
}
public override void Deserialize(byte[] array)
public override void Deserialize(NetIncomingMessage m)
{
BitReader reader = new BitReader(array);
ID = reader.ReadInt32();
Response = (FileResponse)reader.ReadByte();
ID = m.ReadInt32();
Response = (FileResponse)m.ReadByte();
}
}
@ -90,27 +82,21 @@ namespace RageCoop.Core
public byte[] FileChunk { get; set; }
public override byte[] Serialize()
protected override void Serialize(NetOutgoingMessage m)
{
List<byte> byteArray = new List<byte>();
// The ID from the download
byteArray.AddInt(ID);
// The chunk of the file
byteArray.AddInt(FileChunk.Length);
byteArray.AddRange(FileChunk);
return byteArray.ToArray();
m.Write(ID);
m.WriteByteArray(FileChunk);
}
public override void Deserialize(byte[] array)
public override void Deserialize(NetIncomingMessage m)
{
BitReader reader = new BitReader(array);
ID = reader.ReadInt32();
FileChunk = reader.ReadByteArray();
ID = m.ReadInt32();
FileChunk = m.ReadByteArray();
}
}
@ -119,22 +105,20 @@ namespace RageCoop.Core
public override PacketType Type => PacketType.FileTransferComplete;
public int ID { get; set; }
public override byte[] Serialize()
protected override void Serialize(NetOutgoingMessage m)
{
List<byte> byteArray = new List<byte>();
// The ID for the download
byteArray.AddInt(ID);
return byteArray.ToArray();
m.Write(ID);
}
public override void Deserialize(byte[] array)
public override void Deserialize(NetIncomingMessage m)
{
BitReader reader = new BitReader(array);
ID = reader.ReadInt32();
ID = m.ReadInt32();
}
}
internal class AllResourcesSent : Packet

View File

@ -14,26 +14,26 @@ namespace RageCoop.Core
public string TargetInternal { get; set; }
public string TargetExternal { get; set; }
public bool Connect { get; set; }
public override byte[] Serialize()
protected override void Serialize(NetOutgoingMessage m)
{
List<byte> byteArray = new List<byte>();
byteArray.AddInt(TargetID);
byteArray.AddString(TargetInternal);
byteArray.AddString(TargetExternal);
byteArray.AddBool(Connect);
return byteArray.ToArray();
m.Write(TargetID);
m.Write(TargetInternal);
m.Write(TargetExternal);
m.Write(Connect);
}
public override void Deserialize(byte[] array)
public override void Deserialize(NetIncomingMessage m)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
TargetID = reader.ReadInt32();
TargetInternal = reader.ReadString();
TargetExternal = reader.ReadString();
Connect=reader.ReadBoolean();
TargetID = m.ReadInt32();
TargetInternal = m.ReadString();
TargetExternal = m.ReadString();
Connect=m.ReadBoolean();
#endregion
}
}
@ -46,22 +46,22 @@ namespace RageCoop.Core
/// 1:initial, 2:acknowledged, 3:confirmed
/// </summary>
public byte Status { get;set;}
public override byte[] Serialize()
protected override void Serialize(NetOutgoingMessage m)
{
List<byte> byteArray = new List<byte>();
byteArray.AddInt(Puncher);
byteArray.Add(Status);
return byteArray.ToArray();
m.Write(Puncher);
m.Write(Status);
}
public override void Deserialize(byte[] array)
public override void Deserialize(NetIncomingMessage m)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
Puncher = reader.ReadInt32();
Status = reader.ReadByte();
Puncher = m.ReadInt32();
Status = m.ReadByte();
#endregion
}
}

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using Lidgren.Network;
namespace RageCoop.Core
{
@ -12,16 +13,15 @@ namespace RageCoop.Core
{
public int TargetID { get; set; }
public override PacketType Type => PacketType.ConnectionRequest;
public override byte[] Serialize()
protected override void Serialize(NetOutgoingMessage m)
{
var data=new List<byte>(10);
data.AddInt(TargetID);
return data.ToArray();
m.Write(TargetID);
}
public override void Deserialize(byte[] array)
public override void Deserialize(NetIncomingMessage m)
{
var reader=new BitReader(array);
TargetID = reader.ReadInt32();
TargetID = m.ReadInt32();
}
}
@ -33,16 +33,16 @@ namespace RageCoop.Core
{
public int ID { get; set; }
public override PacketType Type => PacketType.P2PConnect;
public override byte[] Serialize()
protected override void Serialize(NetOutgoingMessage m)
{
var data = new List<byte>(10);
data.AddInt(ID);
return data.ToArray();
m.Write(ID);
}
public override void Deserialize(byte[] array)
public override void Deserialize(NetIncomingMessage m)
{
var reader = new BitReader(array);
ID = reader.ReadInt32();
ID = m.ReadInt32();
}
}
}

View File

@ -55,14 +55,6 @@ namespace RageCoop.Core
Unknown=255
}
internal static class PacketExtensions
{
internal static bool IsSyncEvent(this PacketType p)
{
return (30<=(byte)p)&&((byte)p<=40);
}
}
internal enum ConnectionChannel
{
Default = 0,
@ -153,25 +145,19 @@ namespace RageCoop.Core
internal interface IPacket
{
PacketType Type { get; }
byte[] Serialize();
void Deserialize(byte[] data);
void Deserialize(NetIncomingMessage m);
}
internal abstract class Packet : IPacket
{
public abstract PacketType Type { get; }
public virtual byte[] Serialize()
public void Pack(NetOutgoingMessage m)
{
return new byte[0];
}
public virtual void Deserialize(byte[] array) { }
public void Pack(NetOutgoingMessage message)
{
var d=Serialize();
message.Write((byte)Type);
message.Write(d.Length);
message.Write(d);
m.Write((byte)Type);
Serialize(m);
}
protected virtual void Serialize(NetOutgoingMessage m) { }
public virtual void Deserialize(NetIncomingMessage m) { }
}
}

View File

@ -61,92 +61,92 @@ namespace RageCoop.Core
public float BlipScale { get; set; } = 1;
#endregion
public override byte[] Serialize()
protected override void Serialize(NetOutgoingMessage m)
{
List<byte> byteArray = new List<byte>();
byteArray.AddInt(ID);
byteArray.AddInt(OwnerID);
byteArray.AddRange(BitConverter.GetBytes((ushort)Flags));
byteArray.AddRange(BitConverter.GetBytes(Health));
byteArray.Add(Speed);
m.Write(ID);
m.Write(OwnerID);
m.Write((ushort)Flags);
m.Write(Health);
m.Write(Speed);
if (Flags.HasPedFlag(PedDataFlags.IsRagdoll))
{
byteArray.AddVector3(HeadPosition);
byteArray.AddVector3(RightFootPosition);
byteArray.AddVector3(LeftFootPosition);
m.Write(HeadPosition);
m.Write(RightFootPosition);
m.Write(LeftFootPosition);
}
else
{
if (Speed>=4)
{
byteArray.AddInt(VehicleID);
byteArray.Add((byte)(Seat+3));
m.Write(VehicleID);
m.Write((byte)(Seat+3));
}
byteArray.AddVector3(Position);
m.Write(Position);
}
byteArray.AddVector3(Rotation);
byteArray.AddVector3(Velocity);
m.Write(Rotation);
m.Write(Velocity);
if (Flags.HasPedFlag(PedDataFlags.IsAiming))
{
byteArray.AddVector3(AimCoords);
m.Write(AimCoords);
}
byteArray.AddFloat(Heading);
m.Write(Heading);
if (Flags.HasPedFlag(PedDataFlags.IsFullSync))
{
byteArray.AddInt(ModelHash);
byteArray.AddUint(CurrentWeaponHash);
byteArray.AddRange(Clothes);
m.Write(ModelHash);
m.Write(CurrentWeaponHash);
m.Write(Clothes);
if (WeaponComponents != null)
{
byteArray.Add(0x01);
byteArray.AddRange(BitConverter.GetBytes((ushort)WeaponComponents.Count));
m.Write(true);
m.Write((ushort)WeaponComponents.Count);
foreach (KeyValuePair<uint, bool> component in WeaponComponents)
{
byteArray.AddRange(BitConverter.GetBytes(component.Key));
byteArray.AddRange(BitConverter.GetBytes(component.Value));
m.Write(component.Key);
m.Write(component.Value);
}
}
else
{
// Player weapon doesn't have any components
byteArray.Add(0x00);
m.Write(false);
}
byteArray.Add(WeaponTint);
m.Write(WeaponTint);
byteArray.Add((byte)BlipColor);
m.Write((byte)BlipColor);
if ((byte)BlipColor!=255)
{
byteArray.AddUshort((ushort)BlipSprite);
byteArray.AddFloat(BlipScale);
m.Write((ushort)BlipSprite);
m.Write(BlipScale);
}
}
return byteArray.ToArray();
}
public override void Deserialize(byte[] array)
public override void Deserialize(NetIncomingMessage m)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
ID = reader.ReadInt32();
OwnerID=reader.ReadInt32();
Flags = (PedDataFlags)reader.ReadUInt16();
Health = reader.ReadInt32();
Speed = reader.ReadByte();
ID = m.ReadInt32();
OwnerID=m.ReadInt32();
Flags = (PedDataFlags)m.ReadUInt16();
Health = m.ReadInt32();
Speed = m.ReadByte();
if (Flags.HasPedFlag(PedDataFlags.IsRagdoll))
{
HeadPosition=reader.ReadVector3();
RightFootPosition=reader.ReadVector3();
LeftFootPosition=reader.ReadVector3();
HeadPosition=m.ReadVector3();
RightFootPosition=m.ReadVector3();
LeftFootPosition=m.ReadVector3();
Position=HeadPosition;
}
else
@ -154,54 +154,54 @@ namespace RageCoop.Core
// Vehicle related
if (Speed>=4)
{
VehicleID=reader.ReadInt32();
Seat=(VehicleSeat)(reader.ReadByte()-3);
VehicleID=m.ReadInt32();
Seat=(VehicleSeat)(m.ReadByte()-3);
}
// Read player position
Position = reader.ReadVector3();
Position = m.ReadVector3();
}
Rotation = reader.ReadVector3();
Velocity = reader.ReadVector3();
Rotation = m.ReadVector3();
Velocity = m.ReadVector3();
if (Flags.HasPedFlag(PedDataFlags.IsAiming))
{
// Read player aim coords
AimCoords = reader.ReadVector3();
AimCoords = m.ReadVector3();
}
Heading=reader.ReadSingle();
Heading=m.ReadFloat();
if (Flags.HasPedFlag(PedDataFlags.IsFullSync))
{
// Read player model hash
ModelHash = reader.ReadInt32();
ModelHash = m.ReadInt32();
// Read player weapon hash
CurrentWeaponHash = reader.ReadUInt32();
CurrentWeaponHash = m.ReadUInt32();
// Read player clothes
Clothes =reader.ReadBytes(36);
Clothes =m.ReadBytes(36);
// Read player weapon components
if (reader.ReadBoolean())
if (m.ReadBoolean())
{
WeaponComponents = new Dictionary<uint, bool>();
ushort comCount = reader.ReadUInt16();
ushort comCount = m.ReadUInt16();
for (ushort i = 0; i < comCount; i++)
{
WeaponComponents.Add(reader.ReadUInt32(), reader.ReadBoolean());
WeaponComponents.Add(m.ReadUInt32(), m.ReadBoolean());
}
}
WeaponTint=reader.ReadByte();
WeaponTint=m.ReadByte();
BlipColor=(BlipColor)reader.ReadByte();
BlipColor=(BlipColor)m.ReadByte();
if ((byte)BlipColor!=255)
{
BlipSprite=(BlipSprite)reader.ReadUInt16();
BlipScale=reader.ReadSingle();
BlipSprite=(BlipSprite)m.ReadUInt16();
BlipScale=m.ReadFloat();
}
}
#endregion

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Text;
using GTA.Math;
using System.Net;
using Lidgren.Network;
namespace RageCoop.Core
{
@ -38,62 +39,55 @@ namespace RageCoop.Core
public byte[] PasswordEncrypted { get; set; }
public IPEndPoint InternalEndPoint { get; set; }
public override byte[] Serialize()
protected override void Serialize(NetOutgoingMessage m)
{
List<byte> byteArray = new List<byte>();
// Write Player Ped ID
byteArray.AddRange(BitConverter.GetBytes(PedID));
m.Write(PedID);
// Write Username
byte[] usernameBytes = Encoding.UTF8.GetBytes(Username);
byteArray.AddRange(BitConverter.GetBytes(usernameBytes.Length));
byteArray.AddRange(usernameBytes);
m.Write(Username);
// Write ModVersion
byte[] modVersionBytes = Encoding.UTF8.GetBytes(ModVersion);
byteArray.AddRange(BitConverter.GetBytes(modVersionBytes.Length));
byteArray.AddRange(modVersionBytes);
m.Write(ModVersion);
byteArray.AddString(InternalEndPoint.ToString());
m.Write(InternalEndPoint.ToString());
// Write AesKeyCrypted
byteArray.AddArray(AesKeyCrypted);
m.WriteByteArray(AesKeyCrypted);
// Write AesIVCrypted
byteArray.AddArray(AesIVCrypted);
m.WriteByteArray(AesIVCrypted);
// Write PassHash
byteArray.AddArray(PasswordEncrypted);
m.WriteByteArray(PasswordEncrypted);
return byteArray.ToArray();
}
public override void Deserialize(byte[] array)
public override void Deserialize(NetIncomingMessage m)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
// Read player netHandle
PedID = reader.ReadInt32();
PedID = m.ReadInt32();
// Read Username
Username = reader.ReadString();
Username = m.ReadString();
// Read ModVersion
ModVersion = reader.ReadString();
ModVersion = m.ReadString();
InternalEndPoint=CoreUtils.StringToEndPoint(reader.ReadString());
InternalEndPoint=CoreUtils.StringToEndPoint(m.ReadString());
AesKeyCrypted=reader.ReadByteArray();
AesKeyCrypted=m.ReadByteArray();
AesIVCrypted=reader.ReadByteArray();
AesIVCrypted=m.ReadByteArray();
PasswordEncrypted=reader.ReadByteArray();
PasswordEncrypted=m.ReadByteArray();
#endregion
}
}
@ -101,27 +95,25 @@ namespace RageCoop.Core
{
public PlayerData[] Players { get; set; }
public override PacketType Type => PacketType.HandshakeSuccess;
public override byte[] Serialize()
protected override void Serialize(NetOutgoingMessage m)
{
var data = new List<byte>();
data.AddInt(Players.Length);
m.Write(Players.Length);
foreach(var p in Players)
{
data.AddInt(p.ID);
data.AddString(p.Username);
m.Write(p.ID);
m.Write(p.Username);
}
return data.ToArray();
}
public override void Deserialize(byte[] array)
public override void Deserialize(NetIncomingMessage m)
{
var reader = new BitReader(array);
Players=new PlayerData[reader.ReadInt32()];
Players=new PlayerData[m.ReadInt32()];
for(int i = 0; i<Players.Length; i++)
{
Players[i]=new PlayerData()
{
ID=reader.ReadInt32(),
Username=reader.ReadString(),
ID=m.ReadInt32(),
Username=m.ReadString(),
};
}
}
@ -133,36 +125,24 @@ namespace RageCoop.Core
public string Username { get; set; }
public override byte[] Serialize()
protected override void Serialize(NetOutgoingMessage m)
{
List<byte> byteArray = new List<byte>();
// Write NetHandle
byteArray.AddRange(BitConverter.GetBytes(PedID));
m.Write(PedID);
// Get Username bytes
byte[] usernameBytes = Encoding.UTF8.GetBytes(Username);
// Write UsernameLength
byteArray.AddRange(BitConverter.GetBytes(usernameBytes.Length));
// Write Username
byteArray.AddRange(usernameBytes);
return byteArray.ToArray();
m.Write(Username);
}
public override void Deserialize(byte[] array)
public override void Deserialize(NetIncomingMessage m)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
// Read player netHandle
PedID = reader.ReadInt32();
PedID = m.ReadInt32();
// Read Username
Username = reader.ReadString();
Username = m.ReadString();
#endregion
}
}
@ -172,22 +152,18 @@ namespace RageCoop.Core
public override PacketType Type => PacketType.PlayerDisconnect;
public int PedID { get; set; }
public override byte[] Serialize()
protected override void Serialize(NetOutgoingMessage m)
{
List<byte> byteArray = new List<byte>();
m.Write(PedID);
byteArray.AddRange(BitConverter.GetBytes(PedID));
return byteArray.ToArray();
}
public override void Deserialize(byte[] array)
public override void Deserialize(NetIncomingMessage m)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
PedID = reader.ReadInt32();
PedID = m.ReadInt32();
#endregion
}
}
@ -203,42 +179,38 @@ namespace RageCoop.Core
public float Latency { get; set; }
public Vector3 Position { get; set; }
public bool IsHost;
public override byte[] Serialize()
protected override void Serialize(NetOutgoingMessage m)
{
List<byte> byteArray = new List<byte>();
// Write ID
byteArray.AddRange(BitConverter.GetBytes(PedID));
m.Write(PedID);
// Write Username
byteArray.AddString(Username);
m.Write(Username);
// Write Latency
byteArray.AddFloat(Latency);
m.Write(Latency);
byteArray.AddVector3(Position);
m.Write(Position);
byteArray.AddBool(IsHost);
return byteArray.ToArray();
m.Write(IsHost);
}
public override void Deserialize(byte[] array)
public override void Deserialize(NetIncomingMessage m)
{
BitReader reader = new BitReader(array);
// Read player ID
PedID = reader.ReadInt32();
PedID = m.ReadInt32();
// Read Username
Username = reader.ReadString();
Username = m.ReadString();
Latency=reader.ReadSingle();
Latency=m.ReadFloat();
Position=reader.ReadVector3();
Position=m.ReadVector3();
IsHost=reader.ReadBoolean();
IsHost=m.ReadBoolean();
}
}
@ -249,24 +221,24 @@ namespace RageCoop.Core
public byte[] Modulus;
public byte[] Exponent;
public override byte[] Serialize()
protected override void Serialize(NetOutgoingMessage m)
{
List<byte> byteArray = new List<byte>();
byteArray.AddArray(Modulus);
byteArray.AddArray(Exponent);
return byteArray.ToArray();
m.WriteByteArray(Modulus);
m.WriteByteArray(Exponent);
}
public override void Deserialize(byte[] array)
public override void Deserialize(NetIncomingMessage m)
{
#region NetIncomingMessageToPacket
var reader=new BitReader(array);
Modulus=reader.ReadByteArray();
Exponent=reader.ReadByteArray();
Modulus=m.ReadByteArray();
Exponent=m.ReadByteArray();
#endregion
}

View File

@ -26,57 +26,57 @@ namespace RageCoop.Core
public override byte[] Serialize()
protected override void Serialize(NetOutgoingMessage m)
{
List<byte> byteArray = new List<byte>();
// Write id
byteArray.AddInt(ID);
m.Write(ID);
// Write ShooterID
byteArray.AddInt(ShooterID);
m.Write(ShooterID);
byteArray.AddUint(WeaponHash);
m.Write(WeaponHash);
// Write position
byteArray.AddVector3(Position);
m.Write(Position);
// Write rotation
byteArray.AddVector3(Rotation);
m.Write(Rotation);
// Write velocity
byteArray.AddVector3(Velocity);
byteArray.Add((byte)Flags);
m.Write(Velocity);
m.Write((byte)Flags);
return byteArray.ToArray();
}
public override void Deserialize(byte[] array)
public override void Deserialize(NetIncomingMessage m)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
// Read id
ID = reader.ReadInt32();
ID = m.ReadInt32();
// Read ShooterID
ShooterID= reader.ReadInt32();
ShooterID= m.ReadInt32();
WeaponHash= reader.ReadUInt32();
WeaponHash= m.ReadUInt32();
// Read position
Position = reader.ReadVector3();
Position = m.ReadVector3();
// Read rotation
Rotation = reader.ReadVector3();
Rotation = m.ReadVector3();
// Read velocity
Velocity =reader.ReadVector3();
Velocity =m.ReadVector3();
Flags=(ProjectileDataFlags)reader.ReadByte();
Flags=(ProjectileDataFlags)m.ReadByte();
#endregion
}

View File

@ -19,44 +19,44 @@ namespace RageCoop.Core
public Vector3 StartPosition { get; set; }
public Vector3 EndPosition { get; set; }
public override byte[] Serialize()
protected override void Serialize(NetOutgoingMessage m)
{
List<byte> byteArray = new List<byte>();
// Write OwnerID
byteArray.AddRange(BitConverter.GetBytes(OwnerID));
m.Write(OwnerID);
// Write weapon hash
byteArray.AddRange(BitConverter.GetBytes(WeaponHash));
m.Write(WeaponHash);
// Write StartPosition
byteArray.AddVector3(StartPosition);
m.Write(StartPosition);
// Write EndPosition
byteArray.AddVector3(EndPosition);
m.Write(EndPosition);
return byteArray.ToArray();
}
public override void Deserialize(byte[] array)
public override void Deserialize(NetIncomingMessage m)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
// Read OwnerID
OwnerID=reader.ReadInt32();
OwnerID=m.ReadInt32();
// Read WeponHash
WeaponHash=reader.ReadUInt32();
WeaponHash=m.ReadUInt32();
// Read StartPosition
StartPosition=reader.ReadVector3();
StartPosition=m.ReadVector3();
// Read EndPosition
EndPosition=reader.ReadVector3();
EndPosition=m.ReadVector3();
#endregion
}
}

View File

@ -15,24 +15,24 @@ namespace RageCoop.Core
public bool Hover { get; set; }
public override byte[] Serialize()
protected override void Serialize(NetOutgoingMessage m)
{
List<byte> byteArray = new List<byte>();
byteArray.AddInt(VehicleID);
byteArray.AddBool(Hover);
return byteArray.ToArray();
m.Write(VehicleID);
m.Write(Hover);
}
public override void Deserialize(byte[] array)
public override void Deserialize(NetIncomingMessage m)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
VehicleID=reader.ReadInt32();
Hover=reader.ReadBoolean();
VehicleID=m.ReadInt32();
Hover=m.ReadBoolean();
#endregion
}

View File

@ -16,24 +16,19 @@ namespace RageCoop.Core
public int NewOwnerID { get; set; }
public override byte[] Serialize()
protected override void Serialize(NetOutgoingMessage m)
{
List<byte> byteArray = new List<byte>();
byteArray.AddInt(ID);
byteArray.AddInt(NewOwnerID);
return byteArray.ToArray();
m.Write(ID);
m.Write(NewOwnerID);
}
public override void Deserialize(byte[] array)
public override void Deserialize(NetIncomingMessage m)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
ID=reader.ReadInt32();
NewOwnerID=reader.ReadInt32();
ID=m.ReadInt32();
NewOwnerID=m.ReadInt32();
#endregion
}

View File

@ -14,22 +14,22 @@ namespace RageCoop.Core
public override PacketType Type => PacketType.PedKilled;
public int VictimID { get; set; }
public override byte[] Serialize()
protected override void Serialize(NetOutgoingMessage m)
{
List<byte> byteArray = new List<byte>();
byteArray.AddInt(VictimID);
return byteArray.ToArray();
m.Write(VictimID);
}
public override void Deserialize(byte[] array)
public override void Deserialize(NetIncomingMessage m)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
VictimID=reader.ReadInt32();
VictimID=m.ReadInt32();
#endregion
}

View File

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Text;
using GTA.Math;
using Lidgren.Network;
namespace RageCoop.Core
{
@ -18,31 +19,31 @@ namespace RageCoop.Core
public Vector3 StartPosition { get; set; }
public Vector3 EndPosition { get; set; }
public override byte[] Serialize()
protected override void Serialize(NetOutgoingMessage m)
{
List<byte> byteArray = new List<byte>();
byteArray.AddInt(OwnerID);
byteArray.AddUshort(Bone);
byteArray.AddUint(WeaponHash);
byteArray.AddVector3(StartPosition);
byteArray.AddVector3(EndPosition);
return byteArray.ToArray();
m.Write(OwnerID);
m.Write(Bone);
m.Write(WeaponHash);
m.Write(StartPosition);
m.Write(EndPosition);
}
public override void Deserialize(byte[] array)
public override void Deserialize(NetIncomingMessage m)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
OwnerID=reader.ReadInt32();
Bone=reader.ReadUInt16();
WeaponHash=reader.ReadUInt32();
StartPosition=reader.ReadVector3();
EndPosition=reader.ReadVector3();
OwnerID=m.ReadInt32();
Bone=m.ReadUInt16();
WeaponHash=m.ReadUInt32();
StartPosition=m.ReadVector3();
EndPosition=m.ReadVector3();
#endregion
}
}

View File

@ -58,198 +58,170 @@ namespace RageCoop.Core
public string LicensePlate { get; set; }
#endregion
public override byte[] Serialize()
protected override void Serialize(NetOutgoingMessage m)
{
List<byte> byteArray = new List<byte>(100);
byteArray.AddInt(ID);
byteArray.AddInt(OwnerID);
byteArray.AddUshort((ushort)Flags);
byteArray.AddVector3(Position);
byteArray.AddQuaternion(Quaternion);
byteArray.AddVector3(Velocity);
byteArray.AddVector3(RotationVelocity);
byteArray.AddFloat(ThrottlePower);
byteArray.AddFloat(BrakePower);
byteArray.AddFloat(SteeringAngle);
m.Write(ID);
m.Write(OwnerID);
m.Write((ushort)Flags);
m.Write(Position);
m.Write(Quaternion);
m.Write(Velocity);
m.Write(RotationVelocity);
m.Write(ThrottlePower);
m.Write(BrakePower);
m.Write(SteeringAngle);
if (Flags.HasVehFlag(VehicleDataFlags.IsDeluxoHovering))
{
byteArray.AddFloat(DeluxoWingRatio);
m.Write(DeluxoWingRatio);
}
if (Flags.HasVehFlag(VehicleDataFlags.IsFullSync))
{
byteArray.AddInt(ModelHash);
byteArray.AddFloat(EngineHealth);
m.Write(ModelHash);
m.Write(EngineHealth);
// Check
if (Flags.HasVehFlag(VehicleDataFlags.IsAircraft))
{
// Write the vehicle landing gear
byteArray.Add(LandingGear);
m.Write(LandingGear);
}
if (Flags.HasVehFlag(VehicleDataFlags.HasRoof))
{
byteArray.Add(RoofState);
m.Write(RoofState);
}
// Write vehicle colors
byteArray.Add(Colors[0]);
byteArray.Add(Colors[1]);
m.Write(Colors[0]);
m.Write(Colors[1]);
// Write vehicle mods
// Write the count of mods
byteArray.AddRange(BitConverter.GetBytes((short)Mods.Count));
m.Write((short)Mods.Count);
// Loop the dictionary and add the values
foreach (KeyValuePair<int, int> mod in Mods)
{
// Write the mod value
byteArray.AddRange(BitConverter.GetBytes(mod.Key));
byteArray.AddRange(BitConverter.GetBytes(mod.Value));
m.Write(mod.Key);
m.Write(mod.Value);
}
if (!DamageModel.Equals(default(VehicleDamageModel)))
{
// Write boolean = true
byteArray.Add(0x01);
m.Write(true);
// Write vehicle damage model
byteArray.Add(DamageModel.BrokenDoors);
byteArray.Add(DamageModel.OpenedDoors);
byteArray.Add(DamageModel.BrokenWindows);
byteArray.AddRange(BitConverter.GetBytes(DamageModel.BurstedTires));
byteArray.Add(DamageModel.LeftHeadLightBroken);
byteArray.Add(DamageModel.RightHeadLightBroken);
m.Write(DamageModel.BrokenDoors);
m.Write(DamageModel.OpenedDoors);
m.Write(DamageModel.BrokenWindows);
m.Write(DamageModel.BurstedTires);
m.Write(DamageModel.LeftHeadLightBroken);
m.Write(DamageModel.RightHeadLightBroken);
}
else
{
// Write boolean = false
byteArray.Add(0x00);
m.Write(false);
}
// Write LockStatus
byteArray.Add((byte)LockStatus);
m.Write((byte)LockStatus);
// Write RadioStation
byteArray.Add(RadioStation);
m.Write(RadioStation);
// Write LicensePlate
while (LicensePlate.Length<8)
{
LicensePlate+=" ";
}
if (LicensePlate.Length>8)
{
LicensePlate=new string(LicensePlate.Take(8).ToArray());
}
byteArray.AddRange(Encoding.ASCII.GetBytes(LicensePlate));
m.Write(LicensePlate);
byteArray.Add((byte)(Livery+1));
m.Write((byte)(Livery+1));
}
return byteArray.ToArray();
}
public override void Deserialize(byte[] array)
public override void Deserialize(NetIncomingMessage m)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
// Read vehicle id
ID = reader.ReadInt32();
OwnerID = reader.ReadInt32();
Flags=(VehicleDataFlags)reader.ReadUInt16();
// Read position
Position = reader.ReadVector3();
// Read quaternion
Quaternion=reader.ReadQuaternion();
// Read velocity
Velocity =reader.ReadVector3();
// Read rotation velocity
RotationVelocity=reader.ReadVector3();
// Read throttle power
ThrottlePower=reader.ReadSingle();
// Read brake power
BrakePower=reader.ReadSingle();
// Read steering angle
SteeringAngle = reader.ReadSingle();
ID = m.ReadInt32();
OwnerID = m.ReadInt32();
Flags=(VehicleDataFlags)m.ReadUInt16();
Position = m.ReadVector3();
Quaternion=m.ReadQuaternion();
Velocity =m.ReadVector3();
RotationVelocity=m.ReadVector3();
ThrottlePower=m.ReadFloat();
BrakePower=m.ReadFloat();
SteeringAngle = m.ReadFloat();
if (Flags.HasVehFlag(VehicleDataFlags.IsDeluxoHovering))
{
DeluxoWingRatio = reader.ReadSingle();
DeluxoWingRatio = m.ReadFloat();
}
if (Flags.HasVehFlag(VehicleDataFlags.IsFullSync))
{
// Read vehicle model hash
ModelHash = reader.ReadInt32();
ModelHash = m.ReadInt32();
// Read vehicle engine health
EngineHealth = reader.ReadSingle();
EngineHealth = m.ReadFloat();
// Check
if (Flags.HasVehFlag(VehicleDataFlags.IsAircraft))
{
// Read vehicle landing gear
LandingGear = reader.ReadByte();
LandingGear = m.ReadByte();
}
if (Flags.HasVehFlag(VehicleDataFlags.HasRoof))
{
RoofState=reader.ReadByte();
RoofState=m.ReadByte();
}
// Read vehicle colors
byte vehColor1 = reader.ReadByte();
byte vehColor2 = reader.ReadByte();
byte vehColor1 = m.ReadByte();
byte vehColor2 = m.ReadByte();
Colors = new byte[] { vehColor1, vehColor2 };
// Read vehicle mods
// Create new Dictionary
Mods = new Dictionary<int, int>();
// Read count of mods
short vehModCount = reader.ReadInt16();
short vehModCount = m.ReadInt16();
// Loop
for (int i = 0; i < vehModCount; i++)
{
// Read the mod value
Mods.Add(reader.ReadInt32(), reader.ReadInt32());
Mods.Add(m.ReadInt32(), m.ReadInt32());
}
if (reader.ReadBoolean())
if (m.ReadBoolean())
{
// Read vehicle damage model
DamageModel = new VehicleDamageModel()
{
BrokenDoors = reader.ReadByte(),
OpenedDoors=reader.ReadByte(),
BrokenWindows = reader.ReadByte(),
BurstedTires = reader.ReadInt16(),
LeftHeadLightBroken = reader.ReadByte(),
RightHeadLightBroken = reader.ReadByte()
BrokenDoors = m.ReadByte(),
OpenedDoors=m.ReadByte(),
BrokenWindows = m.ReadByte(),
BurstedTires = m.ReadInt16(),
LeftHeadLightBroken = m.ReadByte(),
RightHeadLightBroken = m.ReadByte()
};
}
// Read LockStatus
LockStatus=(VehicleLockStatus)reader.ReadByte();
LockStatus=(VehicleLockStatus)m.ReadByte();
// Read RadioStation
RadioStation=reader.ReadByte();
RadioStation=m.ReadByte();
LicensePlate=Encoding.ASCII.GetString(reader.ReadBytes(8));
LicensePlate=m.ReadString();
Livery=(int)(reader.ReadByte()-1);
Livery=(int)(m.ReadByte()-1);
}
#endregion
}

View File

@ -1,4 +1,5 @@
using System.Collections.Generic;
using Lidgren.Network;
namespace RageCoop.Core
{
@ -10,20 +11,19 @@ namespace RageCoop.Core
public byte[] Buffer { get; set; }
public int Recorded { get; set; }
public override PacketType Type => PacketType.Voice;
public override byte[] Serialize()
protected override void Serialize(NetOutgoingMessage m)
{
var data = new List<byte>();
data.AddInt(ID);
data.AddArray(Buffer);
data.AddInt(Recorded);
return data.ToArray();
m.Write(ID);
m.Write(Buffer);
m.Write(Recorded);
}
public override void Deserialize(byte[] array)
public override void Deserialize(NetIncomingMessage m)
{
var reader = new BitReader(array);
ID = reader.ReadInt32();
Buffer = reader.ReadByteArray();
Recorded = reader.ReadInt32();
ID = m.ReadInt32();
Buffer = m.ReadByteArray();
Recorded = m.ReadInt32();
}
}
}

View File

@ -71,7 +71,7 @@ namespace RageCoop.Server
}
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
packet.Pack(outgoingMessage);
MainNetServer.SendMessage(outgoingMessage, c.Connection, NetDeliveryMethod.UnreliableSequenced, (byte)ConnectionChannel.PedSync);
MainNetServer.SendMessage(outgoingMessage, c.Connection, NetDeliveryMethod.UnreliableSequenced, (byte)ConnectionChannel.VehicleSync);
}
}
private void ProjectileSync(Packets.ProjectileSync packet, Client client)

View File

@ -56,9 +56,7 @@ namespace RageCoop.Server
{
try
{
int len = message.ReadInt32();
byte[] data = message.ReadBytes(len);
GetHandshake(message.SenderConnection, data.GetPacket<Packets.Handshake>());
GetHandshake(message.SenderConnection, message.GetPacket<Packets.Handshake>());
}
catch (Exception e)
{
@ -106,7 +104,7 @@ namespace RageCoop.Server
int id = message.ReadInt32();
if (PendingResponses.TryGetValue(id, out var callback))
{
callback((PacketType)message.ReadByte(), message.ReadBytes(message.ReadInt32()));
callback((PacketType)message.ReadByte(), message);
PendingResponses.Remove(id);
}
break;
@ -114,19 +112,23 @@ namespace RageCoop.Server
case PacketType.Request:
{
int id = message.ReadInt32();
if (RequestHandlers.TryGetValue((PacketType)message.ReadByte(), out var handler))
var reqType = (PacketType)message.ReadByte();
if (RequestHandlers.TryGetValue(reqType, out var handler))
{
var response = MainNetServer.CreateMessage();
response.Write((byte)PacketType.Response);
response.Write(id);
handler(message.ReadBytes(message.ReadInt32()), sender).Pack(response);
handler(message, sender).Pack(response);
MainNetServer.SendMessage(response, message.SenderConnection, NetDeliveryMethod.ReliableOrdered);
}
else
{
Logger.Warning("Did not find a request handler of type: " + reqType);
}
break;
}
default:
{
byte[] data = message.ReadBytes(message.ReadInt32());
if (type.IsSyncEvent())
{
// Sync Events
@ -139,8 +141,7 @@ namespace RageCoop.Server
{
var outgoingMessage = MainNetServer.CreateMessage();
outgoingMessage.Write((byte)type);
outgoingMessage.Write(data.Length);
outgoingMessage.Write(data);
outgoingMessage.Write(message.ReadBytes(message.LengthBytes-1));
MainNetServer.SendMessage(outgoingMessage, toSend, NetDeliveryMethod.UnreliableSequenced, (byte)ConnectionChannel.SyncEvents);
}
}
@ -151,7 +152,7 @@ namespace RageCoop.Server
}
else
{
HandlePacket(type, data, sender);
HandlePacket(type, message, sender);
}
break;
}
@ -191,22 +192,22 @@ namespace RageCoop.Server
MainNetServer.Recycle(message);
}
private void HandlePacket(PacketType type, byte[] data, Client sender)
private void HandlePacket(PacketType type, NetIncomingMessage msg, Client sender)
{
try
{
switch (type)
{
case PacketType.PedSync:
PedSync(data.GetPacket<Packets.PedSync>(), sender);
PedSync(msg.GetPacket<Packets.PedSync>(), sender);
break;
case PacketType.VehicleSync:
VehicleSync(data.GetPacket<Packets.VehicleSync>(), sender);
VehicleSync(msg.GetPacket<Packets.VehicleSync>(), sender);
break;
case PacketType.ProjectileSync:
ProjectileSync(data.GetPacket<Packets.ProjectileSync>(), sender);
ProjectileSync(msg.GetPacket<Packets.ProjectileSync>(), sender);
break;
case PacketType.ChatMessage:
@ -215,7 +216,7 @@ namespace RageCoop.Server
{
return Security.Decrypt(b, sender.EndPoint);
});
packet.Deserialize(data);
packet.Deserialize(msg);
ChatMessageReceived(packet.Username, packet.Message, sender);
}
break;
@ -224,7 +225,7 @@ namespace RageCoop.Server
{
if (Settings.UseVoice && !Settings.UseP2P)
{
Forward(data.GetPacket<Packets.Voice>(), sender, ConnectionChannel.Voice);
Forward(msg.GetPacket<Packets.Voice>(), sender, ConnectionChannel.Voice);
}
}
break;
@ -232,7 +233,7 @@ namespace RageCoop.Server
case PacketType.CustomEvent:
{
Packets.CustomEvent packet = new Packets.CustomEvent();
packet.Deserialize(data);
packet.Deserialize(msg);
QueueJob(() => API.Events.InvokeCustomEventReceived(packet, sender));
}
break;

View File

@ -55,8 +55,8 @@ namespace RageCoop.Server
private readonly Timer _updateTimer = new();
private readonly Worker _worker;
private readonly HashSet<char> _allowedCharacterSet;
private Dictionary<int,Action<PacketType,byte[]>> PendingResponses=new();
internal Dictionary<PacketType, Func<byte[],Client,Packet>> RequestHandlers=new();
private Dictionary<int,Action<PacketType,NetIncomingMessage>> PendingResponses=new();
internal Dictionary<PacketType, Func<NetIncomingMessage,Client,Packet>> RequestHandlers=new();
/// <summary>
/// Get the current server version
/// </summary>
@ -284,12 +284,13 @@ namespace RageCoop.Server
{
throw new InvalidOperationException("Cannot wait for response from the listener thread!");
}
var received=new AutoResetEvent(false);
byte[] response=null;
var received =new AutoResetEvent(false);
T response=new T();
var id = NewRequestID();
PendingResponses.Add(id, (type,p) =>
PendingResponses.Add(id, (type,m) =>
{
response=p;
response.Deserialize(m);
received.Set();
});
var msg = MainNetServer.CreateMessage();
@ -299,9 +300,7 @@ namespace RageCoop.Server
MainNetServer.SendMessage(msg,client.Connection,NetDeliveryMethod.ReliableOrdered,(int)channel);
if (received.WaitOne(timeout))
{
var p = new T();
p.Deserialize(response);
return p;
return response;
}
return null;
@ -318,6 +317,7 @@ namespace RageCoop.Server
stream.Seek(0, SeekOrigin.Begin);
id = id ==default? NewFileID(): id ;
var total = stream.Length;
Logger?.Debug($"Requesting file transfer:{name}, {total}");
if (GetResponse<Packets.FileTransferResponse>(client, new Packets.FileTransferRequest()
{
FileLength= total,

View File

@ -15,7 +15,7 @@ using System.Resources;
[assembly: AssemblyCulture("")]
// Version information
[assembly: AssemblyVersion("1.5.3.156")]
[assembly: AssemblyFileVersion("1.5.3.156")]
[assembly: AssemblyVersion("1.5.3.176")]
[assembly: AssemblyFileVersion("1.5.3.176")]
[assembly: NeutralResourcesLanguageAttribute( "en-US" )]

View File

@ -241,27 +241,35 @@ namespace RageCoop.Server.Scripting
{
Task.Run(() =>
{
if (ClientResources.Count!=0)
try
{
Logger?.Info($"Sending resources to client:{client.Username}");
foreach (var rs in ClientResources)
{
Logger?.Debug(rs.Key);
Server.SendFile(rs.Value,rs.Key+".res", client);
}
Logger?.Info($"Resources sent to:{client.Username}");
}
if (Server.GetResponse<Packets.FileTransferResponse>(client, new Packets.AllResourcesSent())?.Response==FileResponse.Loaded)
{
client.IsReady=true;
Server.API.Events.InvokePlayerReady(client);
}
else
{
Logger?.Warning($"Client {client.Username} failed to load resource.");
if (ClientResources.Count != 0)
{
Logger?.Info($"Sending resources to client:{client.Username}");
foreach (var rs in ClientResources)
{
Logger?.Debug(rs.Key);
Server.SendFile(rs.Value, rs.Key + ".res", client);
}
Logger?.Info($"Resources sent to:{client.Username}");
}
if (Server.GetResponse<Packets.FileTransferResponse>(client, new Packets.AllResourcesSent())?.Response == FileResponse.Loaded)
{
client.IsReady = true;
Server.API.Events.InvokePlayerReady(client);
}
else
{
Logger?.Warning($"Client {client.Username} failed to load resource.");
}
}
catch(Exception ex)
{
Logger.Error("Failed to send resource to client: " + client.Username, ex);
client.Kick("Resource error!");
}
});
}
}

View File

@ -35,22 +35,6 @@ namespace RageCoop.Server
return "";
}
}
public static (byte, byte[]) GetBytesFromObject(object obj)
{
return obj switch
{
byte _ => (0x01, BitConverter.GetBytes((byte)obj)),
short _ => (0x02, BitConverter.GetBytes((short)obj)),
ushort _ => (0x03, BitConverter.GetBytes((ushort)obj)),
int _ => (0x04, BitConverter.GetBytes((int)obj)),
uint _ => (0x05, BitConverter.GetBytes((uint)obj)),
long _ => (0x06, BitConverter.GetBytes((long)obj)),
ulong _ => (0x07, BitConverter.GetBytes((ulong)obj)),
float _ => (0x08, BitConverter.GetBytes((float)obj)),
bool _ => (0x09, BitConverter.GetBytes((bool)obj)),
_ => (0x0, null),
};
}
public static List<NetConnection> Exclude(this IEnumerable<NetConnection> connections,NetConnection toExclude)
{
return new(connections.Where(e => e != toExclude));