P2P connectivity
This commit is contained in:
@ -41,11 +41,13 @@ namespace RageCoop.Client
|
|||||||
internal static Vector3 PlayerPosition;
|
internal static Vector3 PlayerPosition;
|
||||||
internal static Scripting.Resources Resources = null;
|
internal static Scripting.Resources Resources = null;
|
||||||
private static List<Func<bool>> QueuedActions = new List<Func<bool>>();
|
private static List<Func<bool>> QueuedActions = new List<Func<bool>>();
|
||||||
|
public static Worker Worker;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Don't use it!
|
/// Don't use it!
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Main()
|
public Main()
|
||||||
{
|
{
|
||||||
|
Worker = new Worker("RageCoop.Client.Main.Worker", Logger);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Settings = Util.ReadSettings();
|
Settings = Util.ReadSettings();
|
||||||
|
@ -11,7 +11,7 @@ namespace RageCoop.Client
|
|||||||
internal static partial class Networking
|
internal static partial class Networking
|
||||||
{
|
{
|
||||||
public static NetPeer Peer;
|
public static NetPeer Peer;
|
||||||
public static float Latency = 0;
|
public static float Latency => ServerConnection.AverageRoundtripTime/2;
|
||||||
public static bool ShowNetworkInfo = false;
|
public static bool ShowNetworkInfo = false;
|
||||||
public static Security Security;
|
public static Security Security;
|
||||||
public static NetConnection ServerConnection;
|
public static NetConnection ServerConnection;
|
||||||
@ -22,18 +22,22 @@ namespace RageCoop.Client
|
|||||||
static Networking()
|
static Networking()
|
||||||
{
|
{
|
||||||
Security=new Security(Main.Logger);
|
Security=new Security(Main.Logger);
|
||||||
RequestHandlers.Add(PacketType.PingPong, (b) =>
|
|
||||||
{
|
|
||||||
return new Packets.PingPong();
|
|
||||||
});
|
|
||||||
Task.Run(() =>
|
Task.Run(() =>
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (Peer!=null)
|
if (Peer!=null)
|
||||||
{
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
ProcessMessage(Peer.WaitMessage(200));
|
ProcessMessage(Peer.WaitMessage(200));
|
||||||
}
|
}
|
||||||
|
catch(Exception ex)
|
||||||
|
{
|
||||||
|
Main.Logger.Error(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Thread.Sleep(20);
|
Thread.Sleep(20);
|
||||||
@ -64,7 +68,9 @@ namespace RageCoop.Client
|
|||||||
{
|
{
|
||||||
AutoFlushSendQueue = false,
|
AutoFlushSendQueue = false,
|
||||||
SimulatedMinimumLatency =SimulatedLatency,
|
SimulatedMinimumLatency =SimulatedLatency,
|
||||||
AcceptIncomingConnections = true
|
AcceptIncomingConnections = true,
|
||||||
|
MaximumConnections = 32,
|
||||||
|
PingInterval = 5
|
||||||
};
|
};
|
||||||
|
|
||||||
config.EnableMessageType(NetIncomingMessageType.UnconnectedData);
|
config.EnableMessageType(NetIncomingMessageType.UnconnectedData);
|
||||||
@ -110,7 +116,7 @@ namespace RageCoop.Client
|
|||||||
Username =username,
|
Username =username,
|
||||||
ModVersion = Main.CurrentVersion,
|
ModVersion = Main.CurrentVersion,
|
||||||
PasswordEncrypted=Security.Encrypt(password.GetBytes()),
|
PasswordEncrypted=Security.Encrypt(password.GetBytes()),
|
||||||
InternalEndPoint = (System.Net.IPEndPoint)Peer.Socket.LocalEndPoint
|
InternalEndPoint = new System.Net.IPEndPoint(CoreUtils.GetLocalAddress(ip[0]),Peer.Port)
|
||||||
};
|
};
|
||||||
|
|
||||||
Security.GetSymmetricKeysCrypted(out handshake.AesKeyCrypted, out handshake.AesIVCrypted);
|
Security.GetSymmetricKeysCrypted(out handshake.AesKeyCrypted, out handshake.AesIVCrypted);
|
||||||
@ -135,7 +141,7 @@ namespace RageCoop.Client
|
|||||||
#region -- PLAYER --
|
#region -- PLAYER --
|
||||||
private static void PlayerConnect(Packets.PlayerConnect packet)
|
private static void PlayerConnect(Packets.PlayerConnect packet)
|
||||||
{
|
{
|
||||||
var p = new PlayerData
|
var p = new Player
|
||||||
{
|
{
|
||||||
PedID = packet.PedID,
|
PedID = packet.PedID,
|
||||||
Username= packet.Username,
|
Username= packet.Username,
|
||||||
|
@ -36,18 +36,31 @@ namespace RageCoop.Client
|
|||||||
{
|
{
|
||||||
case NetIncomingMessageType.StatusChanged:
|
case NetIncomingMessageType.StatusChanged:
|
||||||
NetConnectionStatus status = (NetConnectionStatus)message.ReadByte();
|
NetConnectionStatus status = (NetConnectionStatus)message.ReadByte();
|
||||||
|
|
||||||
string reason = message.ReadString();
|
string reason = message.ReadString();
|
||||||
|
|
||||||
switch (status)
|
switch (status)
|
||||||
{
|
{
|
||||||
case NetConnectionStatus.InitiatedConnect:
|
case NetConnectionStatus.InitiatedConnect:
|
||||||
#if !NON_INTERACTIVE
|
if (message.SenderConnection==ServerConnection)
|
||||||
|
{
|
||||||
|
|
||||||
CoopMenu.InitiateConnectionMenuSetting();
|
CoopMenu.InitiateConnectionMenuSetting();
|
||||||
#endif
|
}
|
||||||
break;
|
break;
|
||||||
case NetConnectionStatus.Connected:
|
case NetConnectionStatus.Connected:
|
||||||
|
if (message.SenderConnection==ServerConnection)
|
||||||
|
{
|
||||||
Memory.ApplyPatches();
|
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(() =>
|
Main.QueueAction(() =>
|
||||||
{
|
{
|
||||||
CoopMenu.ConnectedMenuSetting();
|
CoopMenu.ConnectedMenuSetting();
|
||||||
@ -56,6 +69,18 @@ namespace RageCoop.Client
|
|||||||
});
|
});
|
||||||
|
|
||||||
Main.Logger.Info(">> Connected <<");
|
Main.Logger.Info(">> Connected <<");
|
||||||
|
}
|
||||||
|
else if (PlayerList.PendingConnections.TryGetValue(message.SenderEndPoint.ToString(),out var player))
|
||||||
|
{
|
||||||
|
PlayerList.PendingConnections.Remove(message.SenderEndPoint.ToString());
|
||||||
|
Main.Logger.Debug($"Connection to {player.Username},{player.PedID},{player.Connection.Status} established, sending ID...");
|
||||||
|
// Inform target our ID
|
||||||
|
SendTo(new Packets.ConnectionEstablished()
|
||||||
|
{
|
||||||
|
ID=Main.LocalPlayerID
|
||||||
|
}, player.Connection, ConnectionChannel.Default, NetDeliveryMethod.ReliableOrdered);
|
||||||
|
Peer.FlushSendQueue();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case NetConnectionStatus.Disconnected:
|
case NetConnectionStatus.Disconnected:
|
||||||
if (message.SenderConnection==ServerConnection)
|
if (message.SenderConnection==ServerConnection)
|
||||||
@ -75,12 +100,25 @@ namespace RageCoop.Client
|
|||||||
GTA.UI.Notification.Show("~r~Disconnected: " + reason));
|
GTA.UI.Notification.Show("~r~Disconnected: " + reason));
|
||||||
Main.Resources.Unload();
|
Main.Resources.Unload();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case NetIncomingMessageType.NatIntroductionSuccess:
|
||||||
|
{
|
||||||
|
var playerID = int.Parse(message.ReadString());
|
||||||
|
// Main.Logger.Debug("NatIntroductionSuccess received from "+message.SenderEndPoint+" "+playerID);
|
||||||
|
if (PlayerList.Players.TryGetValue(playerID, out var player) && (player.Connection==null || player.Connection.Status==NetConnectionStatus.Disconnected))
|
||||||
|
{
|
||||||
|
Main.Logger.Debug($"Establishing direct connection to {player.Username},{player.PedID}");
|
||||||
|
player.Connection=Peer.Connect(message.SenderEndPoint);
|
||||||
|
var ep = message.SenderEndPoint.ToString();
|
||||||
|
if (!PlayerList.PendingConnections.ContainsKey(ep))
|
||||||
|
{
|
||||||
|
PlayerList.PendingConnections.Add(ep, player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case NetIncomingMessageType.Data:
|
case NetIncomingMessageType.Data:
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -123,7 +161,7 @@ namespace RageCoop.Client
|
|||||||
{
|
{
|
||||||
byte[] data = message.ReadBytes(message.ReadInt32());
|
byte[] data = message.ReadBytes(message.ReadInt32());
|
||||||
|
|
||||||
HandlePacket(packetType, data);
|
HandlePacket(packetType, data,message.SenderConnection);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -160,6 +198,7 @@ namespace RageCoop.Client
|
|||||||
case NetIncomingMessageType.ErrorMessage:
|
case NetIncomingMessageType.ErrorMessage:
|
||||||
case NetIncomingMessageType.WarningMessage:
|
case NetIncomingMessageType.WarningMessage:
|
||||||
case NetIncomingMessageType.VerboseDebugMessage:
|
case NetIncomingMessageType.VerboseDebugMessage:
|
||||||
|
Main.Logger.Trace(message.ReadString());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -167,11 +206,22 @@ namespace RageCoop.Client
|
|||||||
|
|
||||||
Peer.Recycle(message);
|
Peer.Recycle(message);
|
||||||
}
|
}
|
||||||
private static void HandlePacket(PacketType packetType, byte[] data)
|
private static void HandlePacket(PacketType packetType, byte[] data, NetConnection senderConnection)
|
||||||
{
|
{
|
||||||
|
|
||||||
switch (packetType)
|
switch (packetType)
|
||||||
{
|
{
|
||||||
|
case PacketType.ConnectionEstablished:
|
||||||
|
{
|
||||||
|
var p=new Packets.ConnectionEstablished();
|
||||||
|
p.Deserialize(data);
|
||||||
|
Main.Logger.Debug("Connection message received from "+senderConnection.RemoteEndPoint+","+p.ID);
|
||||||
|
if(PlayerList.Players.TryGetValue(p.ID,out var player)){
|
||||||
|
Main.Logger.Debug($"Direct connection to {player.Username},{player.PedID} has been established");
|
||||||
|
player.Connection=senderConnection;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case PacketType.PlayerConnect:
|
case PacketType.PlayerConnect:
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ using GTA.Native;
|
|||||||
using Lidgren.Network;
|
using Lidgren.Network;
|
||||||
using RageCoop.Core;
|
using RageCoop.Core;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace RageCoop.Client
|
namespace RageCoop.Client
|
||||||
{
|
{
|
||||||
@ -11,18 +12,18 @@ namespace RageCoop.Client
|
|||||||
{
|
{
|
||||||
|
|
||||||
public static int SyncInterval = 30;
|
public static int SyncInterval = 30;
|
||||||
#region -- SEND --
|
public static List<NetConnection> Targets = new List<NetConnection>();
|
||||||
/// <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 = Peer.CreateMessage();
|
NetOutgoingMessage outgoingMessage = Peer.CreateMessage();
|
||||||
p.Pack(outgoingMessage);
|
p.Pack(outgoingMessage);
|
||||||
Peer.SendMessage(outgoingMessage,ServerConnection, method, (int)channel);
|
Peer.SendMessage(outgoingMessage,Targets, method, (int)channel);
|
||||||
|
}
|
||||||
|
public static void SendTo(Packet p,NetConnection connection, ConnectionChannel channel = ConnectionChannel.Default, NetDeliveryMethod method = NetDeliveryMethod.UnreliableSequenced)
|
||||||
|
{
|
||||||
|
NetOutgoingMessage outgoingMessage = Peer.CreateMessage();
|
||||||
|
p.Pack(outgoingMessage);
|
||||||
|
Peer.SendMessage(outgoingMessage, connection, method, (int)channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SendPed(SyncedPed c, bool full)
|
public static void SendPed(SyncedPed c, bool full)
|
||||||
@ -101,16 +102,16 @@ namespace RageCoop.Client
|
|||||||
Flags = veh.GetVehicleFlags(),
|
Flags = veh.GetVehicleFlags(),
|
||||||
SteeringAngle = veh.SteeringAngle,
|
SteeringAngle = veh.SteeringAngle,
|
||||||
Position = veh.PredictPosition(),
|
Position = veh.PredictPosition(),
|
||||||
|
Velocity=veh.Velocity,
|
||||||
Quaternion=veh.ReadQuaternion(),
|
Quaternion=veh.ReadQuaternion(),
|
||||||
RotationVelocity=veh.RotationVelocity,
|
RotationVelocity=veh.RotationVelocity,
|
||||||
ThrottlePower = veh.ThrottlePower,
|
ThrottlePower = veh.ThrottlePower,
|
||||||
BrakePower = veh.BrakePower,
|
BrakePower = veh.BrakePower,
|
||||||
};
|
};
|
||||||
var velo = veh.Velocity;
|
if (v.LastVelocity==default) {v.LastVelocity=packet.Velocity; }
|
||||||
if (v.LastVelocity==default) {v.LastVelocity=velo; }
|
packet.Acceleration = (packet.Velocity-v.LastVelocity)*1000/v.LastSentStopWatch.ElapsedMilliseconds;
|
||||||
packet.Acceleration = (velo-v.LastVelocity)*1000/v.LastSentStopWatch.ElapsedMilliseconds;
|
|
||||||
packet.Velocity=(v.LastVelocity = velo) + packet.Acceleration*Latency;
|
|
||||||
v.LastSentStopWatch.Restart();
|
v.LastSentStopWatch.Restart();
|
||||||
|
v.LastVelocity= packet.Velocity;
|
||||||
if (packet.Flags.HasVehFlag(VehicleDataFlags.IsDeluxoHovering)) { packet.DeluxoWingRatio=v.MainVehicle.GetDeluxoWingRatio(); }
|
if (packet.Flags.HasVehFlag(VehicleDataFlags.IsDeluxoHovering)) { packet.DeluxoWingRatio=v.MainVehicle.GetDeluxoWingRatio(); }
|
||||||
if (full)
|
if (full)
|
||||||
{
|
{
|
||||||
@ -185,10 +186,6 @@ namespace RageCoop.Client
|
|||||||
|
|
||||||
Peer.SendMessage(outgoingMessage,ServerConnection, NetDeliveryMethod.ReliableOrdered, (byte)ConnectionChannel.Chat);
|
Peer.SendMessage(outgoingMessage,ServerConnection, NetDeliveryMethod.ReliableOrdered, (byte)ConnectionChannel.Chat);
|
||||||
Peer.FlushSendQueue();
|
Peer.FlushSendQueue();
|
||||||
|
}
|
||||||
#if DEBUG
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
using GTA;
|
using GTA;
|
||||||
|
using GTA.Math;
|
||||||
using GTA.Native;
|
using GTA.Native;
|
||||||
using RageCoop.Core;
|
using RageCoop.Core;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Lidgren.Network;
|
||||||
|
using System.Net;
|
||||||
|
|
||||||
namespace RageCoop.Client
|
namespace RageCoop.Client
|
||||||
{
|
{
|
||||||
@ -14,7 +17,8 @@ namespace RageCoop.Client
|
|||||||
public static ulong Pressed { get; set; }
|
public static ulong Pressed { get; set; }
|
||||||
|
|
||||||
public static bool LeftAlign = true;
|
public static bool LeftAlign = true;
|
||||||
public static Dictionary<int, PlayerData> Players = new Dictionary<int, PlayerData> { };
|
public static Dictionary<int, Player> Players = new Dictionary<int, Player> { };
|
||||||
|
public static Dictionary<string, Player> PendingConnections = new Dictionary<string, Player>();
|
||||||
public static void Tick()
|
public static void Tick()
|
||||||
{
|
{
|
||||||
if (!Networking.IsOnServer)
|
if (!Networking.IsOnServer)
|
||||||
@ -24,7 +28,7 @@ namespace RageCoop.Client
|
|||||||
|
|
||||||
if ((Util.GetTickCount64() - _lastUpdate) >= 1000)
|
if ((Util.GetTickCount64() - _lastUpdate) >= 1000)
|
||||||
{
|
{
|
||||||
Update(Main.Settings.Username);
|
Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((Util.GetTickCount64() - Pressed) < 5000 && !Main.MainChat.Focused
|
if ((Util.GetTickCount64() - Pressed) < 5000 && !Main.MainChat.Focused
|
||||||
@ -40,7 +44,7 @@ namespace RageCoop.Client
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void Update(string localUsername)
|
private static void Update()
|
||||||
{
|
{
|
||||||
_lastUpdate = Util.GetTickCount64();
|
_lastUpdate = Util.GetTickCount64();
|
||||||
|
|
||||||
@ -48,9 +52,9 @@ namespace RageCoop.Client
|
|||||||
|
|
||||||
int i=0;
|
int i=0;
|
||||||
|
|
||||||
foreach (var player in Players)
|
foreach (var player in Players.Values)
|
||||||
{
|
{
|
||||||
_mainScaleform.CallFunction("SET_DATA_SLOT", i++, $"{player.Value.Latency * 1000:N0}ms", player.Value.Username, 116, 0, i - 1, "", "", 2, "", "", ' ');
|
_mainScaleform.CallFunction("SET_DATA_SLOT", i++, $"{(player.PedID==Main.LocalPlayerID ? Networking.Latency : player.Latency) * 1000:N0}ms", player.Username, 116, 0, i - 1, "", "", 2, "", "", ' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
_mainScaleform.CallFunction("SET_TITLE", "Player list", $"{Players.Count} players");
|
_mainScaleform.CallFunction("SET_TITLE", "Player list", $"{Players.Count} players");
|
||||||
@ -58,37 +62,36 @@ namespace RageCoop.Client
|
|||||||
}
|
}
|
||||||
public static void SetPlayer(int id, string username, float latency = 0)
|
public static void SetPlayer(int id, string username, float latency = 0)
|
||||||
{
|
{
|
||||||
if(id == Main.LocalPlayerID) { Networking.Latency=latency; }
|
|
||||||
Main.Logger.Debug($"{id},{username},{latency}");
|
Main.Logger.Debug($"{id},{username},{latency}");
|
||||||
PlayerData p;
|
Player p;
|
||||||
if (Players.TryGetValue(id, out p))
|
if (Players.TryGetValue(id, out p))
|
||||||
{
|
{
|
||||||
p.Username=username;
|
p.Username=username;
|
||||||
p.PedID=id;
|
p.PedID=id;
|
||||||
p.Latency=latency;
|
p._latencyToServer=latency;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
p = new PlayerData { PedID=id, Username=username, Latency=latency };
|
p = new Player { PedID=id, Username=username, _latencyToServer=latency };
|
||||||
Players.Add(id, p);
|
Players.Add(id, p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public static void UpdatePlayer(Packets.PlayerInfoUpdate packet)
|
public static void UpdatePlayer(Packets.PlayerInfoUpdate packet)
|
||||||
{
|
{
|
||||||
if (packet.PedID == Main.LocalPlayerID) {Main.Logger.Debug("Latency updated"); Networking.Latency=packet.Latency; }
|
|
||||||
var p = GetPlayer(packet.PedID);
|
var p = GetPlayer(packet.PedID);
|
||||||
if (p!=null)
|
if (p!=null)
|
||||||
{
|
{
|
||||||
p.Latency= packet.Latency;
|
p._latencyToServer = packet.Latency;
|
||||||
|
p.Position = packet.Position;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public static PlayerData GetPlayer(int id)
|
public static Player GetPlayer(int id)
|
||||||
{
|
{
|
||||||
PlayerData p;
|
Player p;
|
||||||
Players.TryGetValue(id, out p);
|
Players.TryGetValue(id, out p);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
public static PlayerData GetPlayer(SyncedPed p)
|
public static Player GetPlayer(SyncedPed p)
|
||||||
{
|
{
|
||||||
var player = GetPlayer(p.ID);
|
var player = GetPlayer(p.ID);
|
||||||
if (player!=null)
|
if (player!=null)
|
||||||
@ -106,13 +109,13 @@ namespace RageCoop.Client
|
|||||||
}
|
}
|
||||||
public static void Cleanup()
|
public static void Cleanup()
|
||||||
{
|
{
|
||||||
Players=new Dictionary<int, PlayerData> { };
|
Players=new Dictionary<int, Player> { };
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
internal class PlayerData
|
internal class Player
|
||||||
{
|
{
|
||||||
public string Username { get; internal set; }
|
public string Username { get; internal set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -122,12 +125,16 @@ namespace RageCoop.Client
|
|||||||
{
|
{
|
||||||
get; internal set;
|
get; internal set;
|
||||||
}
|
}
|
||||||
|
public Vector3 Position { get; set; }
|
||||||
public SyncedPed Character { get; set; }
|
public SyncedPed Character { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Player Latency in second.
|
/// Player Latency in seconds, will be the latency to server if not using P2P connection.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public float Latency { get; set; }
|
public float Latency => HasDirectConnection ? Connection.AverageRoundtripTime/2 : _latencyToServer;
|
||||||
|
public float PacketTravelTime => HasDirectConnection ? Connection.AverageRoundtripTime/2 : Networking.Latency+_latencyToServer;
|
||||||
|
public float _latencyToServer = 0;
|
||||||
public bool DisplayNameTag { get; set; } = true;
|
public bool DisplayNameTag { get; set; } = true;
|
||||||
|
public NetConnection Connection { get; set; }
|
||||||
|
public bool HasDirectConnection => Connection?.Status==NetConnectionStatus.Connected;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -285,7 +285,7 @@ namespace RageCoop.Client.Scripting
|
|||||||
Args=args,
|
Args=args,
|
||||||
Hash=eventHash
|
Hash=eventHash
|
||||||
};
|
};
|
||||||
Networking.Send(p, ConnectionChannel.Event, Lidgren.Network.NetDeliveryMethod.ReliableOrdered);
|
Networking.SendTo(p,Networking.ServerConnection, ConnectionChannel.Event, Lidgren.Network.NetDeliveryMethod.ReliableOrdered);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -25,10 +25,27 @@ namespace RageCoop.Client
|
|||||||
/// Network ID for this entity
|
/// Network ID for this entity
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int ID { get; internal set; }
|
public int ID { get; internal set; }
|
||||||
|
|
||||||
|
|
||||||
|
private int _ownerID;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int OwnerID { get; internal set; }
|
public int OwnerID
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _ownerID;
|
||||||
|
}
|
||||||
|
internal set
|
||||||
|
{
|
||||||
|
if (value==_ownerID) { return; }
|
||||||
|
_ownerID = value;
|
||||||
|
Owner=PlayerList.GetPlayer(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Player Owner { get; private set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -49,7 +49,7 @@ namespace RageCoop.Client
|
|||||||
internal BlipColor BlipColor = (BlipColor)255;
|
internal BlipColor BlipColor = (BlipColor)255;
|
||||||
internal BlipSprite BlipSprite = (BlipSprite)0;
|
internal BlipSprite BlipSprite = (BlipSprite)0;
|
||||||
internal float BlipScale = 1;
|
internal float BlipScale = 1;
|
||||||
internal PlayerData Player;
|
internal Player Player;
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -142,7 +142,7 @@ namespace RageCoop.Client
|
|||||||
|
|
||||||
if (IsPlayer)
|
if (IsPlayer)
|
||||||
{
|
{
|
||||||
Main.Logger.Debug("blip:"+Player.Username);
|
// Main.Logger.Debug("blip:"+Player.Username);
|
||||||
Main.QueueAction(() => { PedBlip.Name=Player.Username; });
|
Main.QueueAction(() => { PedBlip.Name=Player.Username; });
|
||||||
}
|
}
|
||||||
PedBlip.Color=BlipColor;
|
PedBlip.Color=BlipColor;
|
||||||
@ -236,7 +236,7 @@ namespace RageCoop.Client
|
|||||||
{
|
{
|
||||||
if (MainPed.Exists())
|
if (MainPed.Exists())
|
||||||
{
|
{
|
||||||
Main.Logger.Debug($"Removing ped {ID}. Reason:CreateCharacter");
|
// Main.Logger.Debug($"Removing ped {ID}. Reason:CreateCharacter");
|
||||||
MainPed.Kill();
|
MainPed.Kill();
|
||||||
MainPed.MarkAsNoLongerNeeded();
|
MainPed.MarkAsNoLongerNeeded();
|
||||||
MainPed.Delete();
|
MainPed.Delete();
|
||||||
|
@ -358,14 +358,14 @@ namespace RageCoop.Client
|
|||||||
void DisplayVehicle(bool touching)
|
void DisplayVehicle(bool touching)
|
||||||
{
|
{
|
||||||
// predict velocity/position
|
// predict velocity/position
|
||||||
_elapsed = Networking.Latency+0.001f*LastSyncedStopWatch.ElapsedMilliseconds;
|
_elapsed = Owner.PacketTravelTime+0.001f*LastSyncedStopWatch.ElapsedMilliseconds;
|
||||||
|
// new LemonUI.Elements.ScaledText(new System.Drawing.PointF(50, 50), Owner.HasDirectConnection+" "+LastSyncedStopWatch.ElapsedMilliseconds).Draw();
|
||||||
_predictedVel = Velocity+Acceleration*_elapsed;
|
_predictedVel = Velocity+Acceleration*_elapsed;
|
||||||
_predictedPos = Position+_elapsed*(LastVelocity+_predictedVel)/2;
|
_predictedPos = Position+_elapsed*(LastVelocity+_predictedVel)/2;
|
||||||
LastVelocity=_predictedVel;
|
LastVelocity=_predictedVel;
|
||||||
var current = MainVehicle.ReadPosition();
|
var current = MainVehicle.ReadPosition();
|
||||||
var dist = current.DistanceTo(Position);
|
var dist = current.DistanceTo(Position);
|
||||||
var cali = ((Velocity.Length()<0.1 && !touching)?dist*4:dist)*(_predictedPos - current);
|
var cali = ((Velocity.Length()<0.1 && !touching)?dist*4:dist)*(_predictedPos - current);
|
||||||
// new LemonUI.Elements.ScaledText(new System.Drawing.PointF(50, 50), dist.ToString()).Draw();
|
|
||||||
|
|
||||||
if (dist<8)
|
if (dist<8)
|
||||||
{
|
{
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
|
using GTA;
|
||||||
using GTA;
|
|
||||||
using GTA.Native;
|
using GTA.Native;
|
||||||
using RageCoop.Client.Scripting;
|
using RageCoop.Client.Scripting;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Threading;
|
using Lidgren.Network;
|
||||||
|
|
||||||
namespace RageCoop.Client
|
namespace RageCoop.Client
|
||||||
{
|
{
|
||||||
@ -291,7 +290,7 @@ namespace RageCoop.Client
|
|||||||
{
|
{
|
||||||
Handle_Projectiles.Remove(p.Handle);
|
Handle_Projectiles.Remove(p.Handle);
|
||||||
}
|
}
|
||||||
Main.Logger.Debug($"Removing projectile {sp.ID}. Reason:{reason}");
|
// Main.Logger.Debug($"Removing projectile {sp.ID}. Reason:{reason}");
|
||||||
p.Explode();
|
p.Explode();
|
||||||
}
|
}
|
||||||
ID_Projectiles.Remove(id);
|
ID_Projectiles.Remove(id);
|
||||||
@ -322,6 +321,7 @@ namespace RageCoop.Client
|
|||||||
|
|
||||||
public static void DoSync()
|
public static void DoSync()
|
||||||
{
|
{
|
||||||
|
UpdateTargets();
|
||||||
#if BENCHMARK
|
#if BENCHMARK
|
||||||
PerfCounter.Restart();
|
PerfCounter.Restart();
|
||||||
Debug.TimeStamps[TimeStamp.CheckProjectiles]=PerfCounter.ElapsedTicks;
|
Debug.TimeStamps[TimeStamp.CheckProjectiles]=PerfCounter.ElapsedTicks;
|
||||||
@ -560,11 +560,19 @@ namespace RageCoop.Client
|
|||||||
Debug.TimeStamps[TimeStamp.VehicleTotal]=PerfCounter.ElapsedTicks;
|
Debug.TimeStamps[TimeStamp.VehicleTotal]=PerfCounter.ElapsedTicks;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
Networking.Peer.FlushSendQueue();
|
||||||
ThreadPool.QueueUserWorkItem((o) => { Networking.Peer.FlushSendQueue(); });
|
}
|
||||||
|
static void UpdateTargets()
|
||||||
|
{
|
||||||
|
Networking.Targets=new List<NetConnection>(PlayerList.Players.Count) { Networking.ServerConnection };
|
||||||
|
foreach (var p in PlayerList.Players.Values.ToArray())
|
||||||
|
{
|
||||||
|
if (p.HasDirectConnection && p.Position.DistanceTo(Main.PlayerPosition)<500)
|
||||||
|
{
|
||||||
|
Networking.Targets.Add(p.Connection);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void RemoveAllFromPlayer(int playerPedId)
|
public static void RemoveAllFromPlayer(int playerPedId)
|
||||||
{
|
{
|
||||||
|
@ -113,7 +113,7 @@ namespace RageCoop.Client
|
|||||||
{
|
{
|
||||||
if (ped.Handle==Game.Player.Character.Handle) { continue; }
|
if (ped.Handle==Game.Player.Character.Handle) { continue; }
|
||||||
|
|
||||||
Main.Logger.Trace($"Removing ped {ped.Handle}. Reason:RemoveTraffic");
|
// Main.Logger.Trace($"Removing ped {ped.Handle}. Reason:RemoveTraffic");
|
||||||
ped.CurrentVehicle?.Delete();
|
ped.CurrentVehicle?.Delete();
|
||||||
ped.Kill();
|
ped.Kill();
|
||||||
ped.Delete();
|
ped.Delete();
|
||||||
@ -131,7 +131,7 @@ namespace RageCoop.Client
|
|||||||
}
|
}
|
||||||
if ((v== null) || (v.IsLocal&&veh.PopulationType!=EntityPopulationType.Mission))
|
if ((v== null) || (v.IsLocal&&veh.PopulationType!=EntityPopulationType.Mission))
|
||||||
{
|
{
|
||||||
Main.Logger.Debug($"Removing Vehicle {veh.Handle}. Reason:ClearTraffic");
|
// Main.Logger.Debug($"Removing Vehicle {veh.Handle}. Reason:ClearTraffic");
|
||||||
|
|
||||||
veh.Delete();
|
veh.Delete();
|
||||||
}
|
}
|
||||||
|
@ -25,8 +25,7 @@ namespace RageCoop.Core
|
|||||||
}
|
}
|
||||||
public override string ReadString()
|
public override string ReadString()
|
||||||
{
|
{
|
||||||
string value = Encoding.UTF8.GetString(ReadBytes(ReadInt32()));
|
return Encoding.UTF8.GetString(ReadBytes(ReadInt32()));
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector3 ReadVector3()
|
public Vector3 ReadVector3()
|
||||||
|
@ -6,6 +6,7 @@ using System.Threading.Tasks;
|
|||||||
using GTA.Math;
|
using GTA.Math;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
@ -100,7 +101,7 @@ namespace RageCoop.Core
|
|||||||
|
|
||||||
//try to use the address as IPv4, otherwise get hostname
|
//try to use the address as IPv4, otherwise get hostname
|
||||||
if (!IPAddress.TryParse(values[0], out ipaddy))
|
if (!IPAddress.TryParse(values[0], out ipaddy))
|
||||||
ipaddy = getIPfromHost(values[0]);
|
ipaddy = GetIPfromHost(values[0]);
|
||||||
}
|
}
|
||||||
else if (values.Length > 2) //ipv6
|
else if (values.Length > 2) //ipv6
|
||||||
{
|
{
|
||||||
@ -141,8 +142,16 @@ namespace RageCoop.Core
|
|||||||
|
|
||||||
return port;
|
return port;
|
||||||
}
|
}
|
||||||
|
public static IPAddress GetLocalAddress(string target= "8.8.8.8")
|
||||||
private static IPAddress getIPfromHost(string p)
|
{
|
||||||
|
using (Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, 0))
|
||||||
|
{
|
||||||
|
socket.Connect(target, 65530);
|
||||||
|
IPEndPoint endPoint = socket.LocalEndPoint as IPEndPoint;
|
||||||
|
return endPoint.Address;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static IPAddress GetIPfromHost(string p)
|
||||||
{
|
{
|
||||||
var hosts = Dns.GetHostAddresses(p);
|
var hosts = Dns.GetHostAddresses(p);
|
||||||
|
|
||||||
|
@ -5,15 +5,6 @@ namespace RageCoop.Core
|
|||||||
{
|
{
|
||||||
internal partial class Packets
|
internal partial class Packets
|
||||||
{
|
{
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Used to measure the connection latency
|
|
||||||
/// </summary>
|
|
||||||
internal class PingPong : Packet
|
|
||||||
{
|
|
||||||
public override PacketType Type => PacketType.PingPong;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Request direct connection to another client
|
/// Request direct connection to another client
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -33,5 +24,26 @@ namespace RageCoop.Core
|
|||||||
TargetID = reader.ReadInt32();
|
TargetID = reader.ReadInt32();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sent to the host when a direct connection has been established
|
||||||
|
/// </summary>
|
||||||
|
internal class ConnectionEstablished : Packet
|
||||||
|
{
|
||||||
|
public int ID { get; set; }
|
||||||
|
public override PacketType Type => PacketType.ConnectionEstablished;
|
||||||
|
public override byte[] Serialize()
|
||||||
|
{
|
||||||
|
var data = new List<byte>(10);
|
||||||
|
data.AddInt(ID);
|
||||||
|
return data.ToArray();
|
||||||
|
}
|
||||||
|
public override void Deserialize(byte[] array)
|
||||||
|
{
|
||||||
|
var reader = new BitReader(array);
|
||||||
|
ID = reader.ReadInt32();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ namespace RageCoop.Core
|
|||||||
Request=6,
|
Request=6,
|
||||||
Response=7,
|
Response=7,
|
||||||
PingPong = 8,
|
PingPong = 8,
|
||||||
|
HandshakeSuccess = 9,
|
||||||
ChatMessage =10,
|
ChatMessage =10,
|
||||||
|
|
||||||
FileTransferChunk=11,
|
FileTransferChunk=11,
|
||||||
@ -30,6 +31,7 @@ namespace RageCoop.Core
|
|||||||
CustomEventQueued = 17,
|
CustomEventQueued = 17,
|
||||||
|
|
||||||
ConnectionRequest=18,
|
ConnectionRequest=18,
|
||||||
|
ConnectionEstablished = 19,
|
||||||
#region Sync
|
#region Sync
|
||||||
|
|
||||||
#region INTERVAL
|
#region INTERVAL
|
||||||
|
@ -1,14 +1,19 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using GTA.Math;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
|
||||||
namespace RageCoop.Core
|
namespace RageCoop.Core
|
||||||
{
|
{
|
||||||
internal partial class Packets
|
internal partial class Packets
|
||||||
{
|
{
|
||||||
internal class Handshake : Packet
|
internal struct PlayerData
|
||||||
|
{
|
||||||
|
public int ID;
|
||||||
|
public string Username;
|
||||||
|
}
|
||||||
|
public class Handshake : Packet
|
||||||
{
|
{
|
||||||
public override PacketType Type => PacketType.Handshake;
|
public override PacketType Type => PacketType.Handshake;
|
||||||
public int PedID { get; set; }
|
public int PedID { get; set; }
|
||||||
@ -92,7 +97,35 @@ namespace RageCoop.Core
|
|||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public class HandshakeSuccess : Packet
|
||||||
|
{
|
||||||
|
public PlayerData[] Players { get; set; }
|
||||||
|
public override PacketType Type => PacketType.HandshakeSuccess;
|
||||||
|
public override byte[] Serialize()
|
||||||
|
{
|
||||||
|
var data = new List<byte>();
|
||||||
|
data.AddInt(Players.Length);
|
||||||
|
foreach(var p in Players)
|
||||||
|
{
|
||||||
|
data.AddInt(p.ID);
|
||||||
|
data.AddString(p.Username);
|
||||||
|
}
|
||||||
|
return data.ToArray();
|
||||||
|
}
|
||||||
|
public override void Deserialize(byte[] array)
|
||||||
|
{
|
||||||
|
var reader = new BitReader(array);
|
||||||
|
Players=new PlayerData[reader.ReadInt32()];
|
||||||
|
for(int i = 0; i<Players.Length; i++)
|
||||||
|
{
|
||||||
|
Players[i]=new PlayerData()
|
||||||
|
{
|
||||||
|
ID=reader.ReadInt32(),
|
||||||
|
Username=reader.ReadString(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
public class PlayerConnect : Packet
|
public class PlayerConnect : Packet
|
||||||
{
|
{
|
||||||
public override PacketType Type => PacketType.PlayerConnect;
|
public override PacketType Type => PacketType.PlayerConnect;
|
||||||
@ -168,6 +201,7 @@ namespace RageCoop.Core
|
|||||||
public int PedID { get; set; }
|
public int PedID { get; set; }
|
||||||
public string Username { get; set; }
|
public string Username { get; set; }
|
||||||
public float Latency { get; set; }
|
public float Latency { get; set; }
|
||||||
|
public Vector3 Position { get; set; }
|
||||||
public override byte[] Serialize()
|
public override byte[] Serialize()
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -176,19 +210,14 @@ namespace RageCoop.Core
|
|||||||
// Write ID
|
// Write ID
|
||||||
byteArray.AddRange(BitConverter.GetBytes(PedID));
|
byteArray.AddRange(BitConverter.GetBytes(PedID));
|
||||||
|
|
||||||
// Get Username bytes
|
|
||||||
byte[] usernameBytes = Encoding.UTF8.GetBytes(Username);
|
|
||||||
|
|
||||||
|
|
||||||
// Write UsernameLength
|
|
||||||
byteArray.AddRange(BitConverter.GetBytes(usernameBytes.Length));
|
|
||||||
|
|
||||||
// Write Username
|
// Write Username
|
||||||
byteArray.AddRange(usernameBytes);
|
byteArray.AddString(Username);
|
||||||
|
|
||||||
// Write Latency
|
// Write Latency
|
||||||
byteArray.AddFloat(Latency);
|
byteArray.AddFloat(Latency);
|
||||||
|
|
||||||
|
byteArray.AddVector3(Position);
|
||||||
|
|
||||||
return byteArray.ToArray();
|
return byteArray.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,6 +232,8 @@ namespace RageCoop.Core
|
|||||||
Username = reader.ReadString();
|
Username = reader.ReadString();
|
||||||
|
|
||||||
Latency=reader.ReadSingle();
|
Latency=reader.ReadSingle();
|
||||||
|
|
||||||
|
Position=reader.ReadVector3();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ namespace RageCoop.Server
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The client's latency in seconds.
|
/// The client's latency in seconds.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public float Latency { get; internal set; }
|
public float Latency => Connection.AverageRoundtripTime/2;
|
||||||
internal readonly Dictionary<int, Action<object>> Callbacks = new();
|
internal readonly Dictionary<int, Action<object>> Callbacks = new();
|
||||||
internal byte[] PublicKey { get; set; }
|
internal byte[] PublicKey { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -80,21 +80,6 @@ namespace RageCoop.Server
|
|||||||
_displayNameTag=value;
|
_displayNameTag=value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
internal void UpdateLatency()
|
|
||||||
{
|
|
||||||
_latencyWatch.Restart();
|
|
||||||
Server.GetResponse<Packets.PingPong>(this, new Packets.PingPong(), ConnectionChannel.PingPong);
|
|
||||||
_latencyWatch.Stop();
|
|
||||||
Latency = (float)_latencyWatch.ElapsedMilliseconds/2000;
|
|
||||||
NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage();
|
|
||||||
new Packets.PlayerInfoUpdate()
|
|
||||||
{
|
|
||||||
PedID=Player.ID,
|
|
||||||
Username=Username,
|
|
||||||
Latency=Latency,
|
|
||||||
}.Pack(outgoingMessage);
|
|
||||||
Server.MainNetServer.SendToAll(outgoingMessage, NetDeliveryMethod.ReliableSequenced, (byte)ConnectionChannel.Default);
|
|
||||||
}
|
|
||||||
#region FUNCTIONS
|
#region FUNCTIONS
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Kick this client
|
/// Kick this client
|
||||||
|
@ -91,9 +91,24 @@ namespace RageCoop.Server
|
|||||||
{
|
{
|
||||||
foreach(var c in ClientsByNetHandle.Values.ToArray())
|
foreach(var c in ClientsByNetHandle.Values.ToArray())
|
||||||
{
|
{
|
||||||
c.UpdateLatency();
|
try
|
||||||
|
{
|
||||||
|
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
|
||||||
|
new Packets.PlayerInfoUpdate()
|
||||||
|
{
|
||||||
|
PedID=c.Player.ID,
|
||||||
|
Username=c.Username,
|
||||||
|
Latency=c.Latency,
|
||||||
|
Position=c.Player.Position
|
||||||
|
}.Pack(outgoingMessage);
|
||||||
|
MainNetServer.SendToAll(outgoingMessage, NetDeliveryMethod.ReliableSequenced, (byte)ConnectionChannel.Default);
|
||||||
}
|
}
|
||||||
Thread.Sleep(3000);
|
catch(Exception ex)
|
||||||
|
{
|
||||||
|
Logger?.Error(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Thread.Sleep(5000);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
_announceThread=new Thread(async () =>
|
_announceThread=new Thread(async () =>
|
||||||
@ -217,7 +232,8 @@ namespace RageCoop.Server
|
|||||||
Port = Settings.Port,
|
Port = Settings.Port,
|
||||||
MaximumConnections = Settings.MaxPlayers,
|
MaximumConnections = Settings.MaxPlayers,
|
||||||
EnableUPnP = false,
|
EnableUPnP = false,
|
||||||
AutoFlushSendQueue = true
|
AutoFlushSendQueue = true,
|
||||||
|
PingInterval=5
|
||||||
};
|
};
|
||||||
|
|
||||||
config.EnableMessageType(NetIncomingMessageType.ConnectionApproval);
|
config.EnableMessageType(NetIncomingMessageType.ConnectionApproval);
|
||||||
@ -375,6 +391,8 @@ namespace RageCoop.Server
|
|||||||
if (type.IsSyncEvent())
|
if (type.IsSyncEvent())
|
||||||
{
|
{
|
||||||
// Sync Events
|
// Sync Events
|
||||||
|
|
||||||
|
if (Settings.UseP2P) { break; }
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var toSend = MainNetServer.Connections.Exclude(message.SenderConnection);
|
var toSend = MainNetServer.Connections.Exclude(message.SenderConnection);
|
||||||
@ -563,8 +581,22 @@ namespace RageCoop.Server
|
|||||||
connection.Deny("Malformed handshak packet!");
|
connection.Deny("Malformed handshak packet!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
var handshakeSuccess = MainNetServer.CreateMessage();
|
||||||
connection.Approve();
|
var currentClients = ClientsByID.Values.ToArray();
|
||||||
|
var players = new Packets.PlayerData[currentClients.Length];
|
||||||
|
for(int i= 0; i<players.Length; i++)
|
||||||
|
{
|
||||||
|
players[i]=new Packets.PlayerData()
|
||||||
|
{
|
||||||
|
ID=currentClients[i].Player.ID,
|
||||||
|
Username=currentClients[i].Username,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
new Packets.HandshakeSuccess()
|
||||||
|
{
|
||||||
|
Players=players
|
||||||
|
}.Pack(handshakeSuccess);
|
||||||
|
connection.Approve(handshakeSuccess);
|
||||||
Client tmpClient;
|
Client tmpClient;
|
||||||
|
|
||||||
// Add the player to Players
|
// Add the player to Players
|
||||||
@ -604,27 +636,6 @@ namespace RageCoop.Server
|
|||||||
API.SendCustomEvent(new() { newClient },CustomEvents.IsHost, true);
|
API.SendCustomEvent(new() { newClient },CustomEvents.IsHost, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send other players to this client
|
|
||||||
ClientsByNetHandle.Values.ForEach(target =>
|
|
||||||
{
|
|
||||||
if (target==newClient) { return; }
|
|
||||||
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
|
|
||||||
new Packets.PlayerConnect()
|
|
||||||
{
|
|
||||||
// NetHandle = targetNetHandle,
|
|
||||||
Username = target.Username,
|
|
||||||
PedID=target.Player.ID,
|
|
||||||
|
|
||||||
}.Pack(outgoingMessage);
|
|
||||||
MainNetServer.SendMessage(outgoingMessage, newClient.Connection, NetDeliveryMethod.ReliableOrdered, 0);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Send all props to this player
|
|
||||||
BaseScript.SendServerPropsTo( new(Entities.ServerProps.Values), new() { newClient});
|
|
||||||
|
|
||||||
// Send all blips to this player
|
|
||||||
BaseScript.SendServerBlipsTo(new(Entities.Blips.Values), new() { newClient});
|
|
||||||
|
|
||||||
// Send new client to all players
|
// Send new client to all players
|
||||||
var cons = MainNetServer.Connections.Exclude(newClient.Connection);
|
var cons = MainNetServer.Connections.Exclude(newClient.Connection);
|
||||||
if (cons.Count!=0)
|
if (cons.Count!=0)
|
||||||
@ -640,6 +651,24 @@ namespace RageCoop.Server
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Send all props to this player
|
||||||
|
BaseScript.SendServerPropsTo( new(Entities.ServerProps.Values), new() { newClient});
|
||||||
|
|
||||||
|
// Send all blips to this player
|
||||||
|
BaseScript.SendServerBlipsTo(new(Entities.Blips.Values), new() { newClient});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Create P2P connection
|
||||||
|
if (Settings.UseP2P)
|
||||||
|
{
|
||||||
|
ClientsByNetHandle.Values.ForEach(target =>
|
||||||
|
{
|
||||||
|
if (target==newClient) { return; }
|
||||||
|
MainNetServer.Introduce(target.InternalEndPoint, target.EndPoint, newClient.InternalEndPoint, newClient.EndPoint, target.Player.ID.ToString());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
Logger?.Info($"Player {newClient.Username} connected!");
|
Logger?.Info($"Player {newClient.Username} connected!");
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(Settings.WelcomeMessage))
|
if (!string.IsNullOrEmpty(Settings.WelcomeMessage))
|
||||||
@ -690,6 +719,7 @@ namespace RageCoop.Server
|
|||||||
_worker.QueueJob(() => API.Events.InvokePlayerUpdate(client));
|
_worker.QueueJob(() => API.Events.InvokePlayerUpdate(client));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Settings.UseP2P) { return; }
|
||||||
foreach (var c in ClientsByNetHandle.Values)
|
foreach (var c in ClientsByNetHandle.Values)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -718,6 +748,9 @@ namespace RageCoop.Server
|
|||||||
{
|
{
|
||||||
_worker.QueueJob(() => Entities.Update(packet, client));
|
_worker.QueueJob(() => Entities.Update(packet, client));
|
||||||
bool isPlayer = packet.ID==client.Player?.LastVehicle?.ID;
|
bool isPlayer = packet.ID==client.Player?.LastVehicle?.ID;
|
||||||
|
|
||||||
|
|
||||||
|
if (Settings.UseP2P) { return; }
|
||||||
foreach (var c in ClientsByNetHandle.Values)
|
foreach (var c in ClientsByNetHandle.Values)
|
||||||
{
|
{
|
||||||
if (c.NetHandle==client.NetHandle) { continue; }
|
if (c.NetHandle==client.NetHandle) { continue; }
|
||||||
@ -742,6 +775,7 @@ namespace RageCoop.Server
|
|||||||
private void ProjectileSync(Packets.ProjectileSync packet, Client client)
|
private void ProjectileSync(Packets.ProjectileSync packet, Client client)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
if (Settings.UseP2P) { return; }
|
||||||
foreach (var c in ClientsByNetHandle.Values)
|
foreach (var c in ClientsByNetHandle.Values)
|
||||||
{
|
{
|
||||||
if (c.NetHandle==client.NetHandle) { continue; }
|
if (c.NetHandle==client.NetHandle) { continue; }
|
||||||
|
@ -84,5 +84,10 @@
|
|||||||
/// List of all allowed username characters
|
/// List of all allowed username characters
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string AllowedUsernameChars { get; set; } = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890-_";
|
public string AllowedUsernameChars { get; set; } = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890-_";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether to use direct connection between players to send entity information
|
||||||
|
/// </summary>
|
||||||
|
public bool UseP2P { get; set; } = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user