Files
RAGECOOP-V/RageCoop.Server/Networking/Server.Connections.cs

198 lines
7.6 KiB
C#
Raw Normal View History

2022-09-08 12:41:56 -07:00
using Lidgren.Network;
2022-08-10 20:42:47 +08:00
using RageCoop.Core;
using RageCoop.Core.Scripting;
using RageCoop.Server.Scripting;
2022-09-08 12:41:56 -07:00
using System;
using System.Linq;
using System.Text;
2022-08-10 20:42:47 +08:00
namespace RageCoop.Server
{
public partial class Server
{
private void DisconnectAndLog(NetConnection senderConnection, PacketType type, Exception e)
{
Logger?.Error($"Error receiving a packet of type {type}");
Logger?.Error(e.Message);
Logger?.Error(e.StackTrace);
senderConnection.Disconnect(e.Message);
}
private void GetHandshake(NetConnection connection, Packets.Handshake packet)
{
Logger?.Debug("New handshake from: [Name: " + packet.Username + " | Address: " + connection.RemoteEndPoint.Address.ToString() + "]");
2022-08-18 17:45:08 +08:00
if (!packet.ModVersion.StartsWith(Version.ToString(3)))
2022-08-10 20:42:47 +08:00
{
2022-08-18 17:45:08 +08:00
connection.Deny($"RAGECOOP version {Version.ToString(3)} required!");
2022-08-10 20:42:47 +08:00
return;
}
if (string.IsNullOrWhiteSpace(packet.Username))
{
connection.Deny("Username is empty or contains spaces!");
return;
}
if (packet.Username.Any(p => !_allowedCharacterSet.Contains(p)))
{
connection.Deny("Username contains special chars!");
return;
}
if (ClientsByNetHandle.Values.Any(x => x.Username.ToLower() == packet.Username.ToLower()))
{
connection.Deny("Username is already taken!");
return;
}
2022-09-05 13:02:09 +02:00
2022-08-10 20:42:47 +08:00
try
{
Security.AddConnection(connection.RemoteEndPoint, packet.AesKeyCrypted, packet.AesIVCrypted);
var args = new HandshakeEventArgs()
{
2022-09-08 12:41:56 -07:00
EndPoint = connection.RemoteEndPoint,
ID = packet.PedID,
Username = packet.Username,
PasswordHash = Security.Decrypt(packet.PasswordEncrypted, connection.RemoteEndPoint).GetString().GetSHA256Hash().ToHexString(),
2022-08-10 20:42:47 +08:00
};
API.Events.InvokePlayerHandshake(args);
if (args.Cancel)
{
connection.Deny(args.DenyReason);
return;
}
}
catch (Exception ex)
{
Logger?.Error($"Cannot process handshake packet from {connection.RemoteEndPoint}");
Logger?.Error(ex);
connection.Deny("Malformed handshak packet!");
return;
}
2022-09-05 13:02:09 +02:00
2022-08-10 20:42:47 +08:00
var handshakeSuccess = MainNetServer.CreateMessage();
var currentClients = ClientsByID.Values.ToArray();
var players = new Packets.PlayerData[currentClients.Length];
2022-09-08 12:41:56 -07:00
for (int i = 0; i < players.Length; i++)
2022-08-10 20:42:47 +08:00
{
2022-09-08 12:41:56 -07:00
players[i] = new Packets.PlayerData()
2022-08-10 20:42:47 +08:00
{
2022-09-08 12:41:56 -07:00
ID = currentClients[i].Player.ID,
Username = currentClients[i].Username,
2022-08-10 20:42:47 +08:00
};
}
2022-09-05 13:02:09 +02:00
2022-08-10 20:42:47 +08:00
new Packets.HandshakeSuccess()
{
2022-09-08 12:41:56 -07:00
Players = players
2022-08-10 20:42:47 +08:00
}.Pack(handshakeSuccess);
connection.Approve(handshakeSuccess);
Client tmpClient;
// Add the player to Players
lock (ClientsByNetHandle)
{
var player = new ServerPed(this)
{
2022-09-08 12:41:56 -07:00
ID = packet.PedID,
2022-08-10 20:42:47 +08:00
};
Entities.Add(player);
ClientsByNetHandle.Add(connection.RemoteUniqueIdentifier,
tmpClient = new Client(this)
{
NetHandle = connection.RemoteUniqueIdentifier,
2022-09-08 12:41:56 -07:00
Connection = connection,
Username = packet.Username,
2022-08-10 20:42:47 +08:00
Player = player,
2022-09-08 12:41:56 -07:00
InternalEndPoint = packet.InternalEndPoint,
2022-08-10 20:42:47 +08:00
}
);
2022-09-08 12:41:56 -07:00
player.Owner = tmpClient;
2022-08-10 20:42:47 +08:00
ClientsByName.Add(packet.Username.ToLower(), tmpClient);
ClientsByID.Add(player.ID, tmpClient);
2022-09-08 12:41:56 -07:00
if (ClientsByNetHandle.Count == 1)
2022-08-10 20:42:47 +08:00
{
2022-09-08 12:41:56 -07:00
_hostClient = tmpClient;
2022-08-10 20:42:47 +08:00
}
}
Logger?.Debug($"Handshake sucess, Player:{packet.Username} PedID:{packet.PedID}");
}
// The connection has been approved, now we need to send all other players to the new player and the new player to all players
private void PlayerConnected(Client newClient)
{
2022-09-08 12:41:56 -07:00
if (newClient == _hostClient)
2022-08-10 20:42:47 +08:00
{
API.SendCustomEvent(new() { newClient }, CustomEvents.IsHost, true);
}
// Send new client to all players
var cons = MainNetServer.Connections.Exclude(newClient.Connection);
2022-09-08 12:41:56 -07:00
if (cons.Count != 0)
2022-08-10 20:42:47 +08:00
{
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
new Packets.PlayerConnect()
{
2022-09-08 12:41:56 -07:00
PedID = newClient.Player.ID,
2022-08-10 20:42:47 +08:00
Username = newClient.Username
}.Pack(outgoingMessage);
MainNetServer.SendMessage(outgoingMessage, cons, 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 });
// Create P2P connection
if (Settings.UseP2P)
{
ClientsByNetHandle.Values.ForEach(target =>
{
2022-09-08 12:41:56 -07:00
if (target == newClient) { return; }
HolePunch(target, newClient);
2022-08-10 20:42:47 +08:00
});
}
Logger?.Info($"Player {newClient.Username} connected!");
if (!string.IsNullOrEmpty(Settings.WelcomeMessage))
{
SendChatMessage("Server", Settings.WelcomeMessage, newClient);
}
}
// Send all players a message that someone has left the server
private void PlayerDisconnected(Client localClient)
{
var cons = MainNetServer.Connections.Exclude(localClient.Connection);
2022-09-08 12:41:56 -07:00
if (cons.Count != 0)
2022-08-10 20:42:47 +08:00
{
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
new Packets.PlayerDisconnect()
{
2022-09-08 12:41:56 -07:00
PedID = localClient.Player.ID,
2022-08-10 20:42:47 +08:00
}.Pack(outgoingMessage);
MainNetServer.SendMessage(outgoingMessage, cons, NetDeliveryMethod.ReliableOrdered, 0);
}
Entities.CleanUp(localClient);
2022-09-06 21:46:35 +08:00
QueueJob(() => API.Events.InvokePlayerDisconnected(localClient));
2022-08-10 20:42:47 +08:00
Logger?.Info($"Player {localClient.Username} disconnected! ID:{localClient.Player.ID}");
if (ClientsByNetHandle.ContainsKey(localClient.NetHandle)) { ClientsByNetHandle.Remove(localClient.NetHandle); }
if (ClientsByName.ContainsKey(localClient.Username.ToLower())) { ClientsByName.Remove(localClient.Username.ToLower()); }
if (ClientsByID.ContainsKey(localClient.Player.ID)) { ClientsByID.Remove(localClient.Player.ID); }
2022-09-08 12:41:56 -07:00
if (localClient == _hostClient)
2022-08-10 20:42:47 +08:00
{
_hostClient = ClientsByNetHandle.Values.FirstOrDefault();
_hostClient?.SendCustomEvent(CustomEvents.IsHost, true);
}
Security.RemoveConnection(localClient.Connection.RemoteEndPoint);
}
}
}