2022-10-23 19:02:39 +08:00
|
|
|
|
using System;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using Lidgren.Network;
|
2022-08-10 20:42:47 +08:00
|
|
|
|
using RageCoop.Core;
|
|
|
|
|
using RageCoop.Core.Scripting;
|
|
|
|
|
using RageCoop.Server.Scripting;
|
|
|
|
|
|
2022-10-23 19:02:39 +08:00
|
|
|
|
namespace RageCoop.Server;
|
|
|
|
|
|
|
|
|
|
public partial class Server
|
2022-08-10 20:42:47 +08:00
|
|
|
|
{
|
2022-10-23 19:02:39 +08:00
|
|
|
|
private void DisconnectAndLog(NetConnection senderConnection, PacketType type, Exception e)
|
2022-08-10 20:42:47 +08:00
|
|
|
|
{
|
2022-10-23 19:02:39 +08:00
|
|
|
|
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 + "]");
|
|
|
|
|
if (!packet.ModVersion.StartsWith(Version.ToString(3)))
|
2022-08-10 20:42:47 +08:00
|
|
|
|
{
|
2022-10-23 19:02:39 +08:00
|
|
|
|
connection.Deny($"RAGECOOP version {Version.ToString(3)} required!");
|
|
|
|
|
return;
|
2022-08-10 20:42:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
2022-10-23 19:02:39 +08:00
|
|
|
|
if (string.IsNullOrWhiteSpace(packet.Username))
|
2022-08-10 20:42:47 +08:00
|
|
|
|
{
|
2022-10-23 19:02:39 +08:00
|
|
|
|
connection.Deny("Username is empty or contains spaces!");
|
|
|
|
|
return;
|
|
|
|
|
}
|
2022-09-05 13:02:09 +02:00
|
|
|
|
|
2022-10-23 19:02:39 +08:00
|
|
|
|
if (packet.Username.Any(p => !_allowedCharacterSet.Contains(p)))
|
|
|
|
|
{
|
|
|
|
|
connection.Deny("Username contains special chars!");
|
|
|
|
|
return;
|
|
|
|
|
}
|
2022-08-10 20:42:47 +08:00
|
|
|
|
|
2022-10-23 19:02:39 +08:00
|
|
|
|
if (ClientsByNetHandle.Values.Any(x => x.Username.ToLower() == packet.Username.ToLower()))
|
|
|
|
|
{
|
|
|
|
|
connection.Deny("Username is already taken!");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
Security.AddConnection(connection.RemoteEndPoint, packet.AesKeyCrypted, packet.AesIVCrypted);
|
|
|
|
|
|
|
|
|
|
var args = new HandshakeEventArgs
|
|
|
|
|
{
|
|
|
|
|
EndPoint = connection.RemoteEndPoint,
|
|
|
|
|
ID = packet.PedID,
|
|
|
|
|
Username = packet.Username,
|
|
|
|
|
PasswordHash = Security.Decrypt(packet.PasswordEncrypted, connection.RemoteEndPoint).GetString()
|
|
|
|
|
.GetSHA256Hash().ToHexString()
|
|
|
|
|
};
|
|
|
|
|
API.Events.InvokePlayerHandshake(args);
|
|
|
|
|
if (args.Cancel)
|
2022-08-10 20:42:47 +08:00
|
|
|
|
{
|
2022-10-23 19:02:39 +08:00
|
|
|
|
connection.Deny(args.DenyReason);
|
2022-08-10 20:42:47 +08:00
|
|
|
|
return;
|
|
|
|
|
}
|
2022-10-23 19:02:39 +08:00
|
|
|
|
}
|
|
|
|
|
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-10-23 19:02:39 +08:00
|
|
|
|
var handshakeSuccess = MainNetServer.CreateMessage();
|
|
|
|
|
var currentClients = ClientsByID.Values.ToArray();
|
|
|
|
|
var players = new Packets.PlayerData[currentClients.Length];
|
|
|
|
|
for (var i = 0; i < players.Length; i++)
|
|
|
|
|
players[i] = new Packets.PlayerData
|
2022-08-10 20:42:47 +08:00
|
|
|
|
{
|
2022-10-23 19:02:39 +08:00
|
|
|
|
ID = currentClients[i].Player.ID,
|
|
|
|
|
Username = currentClients[i].Username
|
|
|
|
|
};
|
2022-09-05 13:02:09 +02:00
|
|
|
|
|
2022-10-23 19:02:39 +08:00
|
|
|
|
new Packets.HandshakeSuccess
|
|
|
|
|
{
|
|
|
|
|
Players = players
|
|
|
|
|
}.Pack(handshakeSuccess);
|
|
|
|
|
connection.Approve(handshakeSuccess);
|
|
|
|
|
Client tmpClient;
|
2022-08-10 20:42:47 +08:00
|
|
|
|
|
2022-10-23 19:02:39 +08:00
|
|
|
|
// Add the player to Players
|
|
|
|
|
lock (ClientsByNetHandle)
|
|
|
|
|
{
|
|
|
|
|
var player = new ServerPed(this)
|
2022-08-10 20:42:47 +08:00
|
|
|
|
{
|
2022-10-23 19:02:39 +08:00
|
|
|
|
ID = packet.PedID
|
|
|
|
|
};
|
|
|
|
|
Entities.Add(player);
|
|
|
|
|
ClientsByNetHandle.Add(connection.RemoteUniqueIdentifier,
|
|
|
|
|
tmpClient = new Client(this)
|
2022-08-10 20:42:47 +08:00
|
|
|
|
{
|
2022-10-23 19:02:39 +08:00
|
|
|
|
NetHandle = connection.RemoteUniqueIdentifier,
|
|
|
|
|
Connection = connection,
|
|
|
|
|
Username = packet.Username,
|
|
|
|
|
Player = player,
|
|
|
|
|
InternalEndPoint = packet.InternalEndPoint
|
2022-08-10 20:42:47 +08:00
|
|
|
|
}
|
2022-10-23 19:02:39 +08:00
|
|
|
|
);
|
|
|
|
|
player.Owner = tmpClient;
|
|
|
|
|
ClientsByName.Add(packet.Username.ToLower(), tmpClient);
|
|
|
|
|
ClientsByID.Add(player.ID, tmpClient);
|
|
|
|
|
if (ClientsByNetHandle.Count == 1) _hostClient = tmpClient;
|
|
|
|
|
}
|
2022-08-10 20:42:47 +08:00
|
|
|
|
|
2022-10-23 19:02:39 +08:00
|
|
|
|
Logger?.Debug($"Handshake sucess, Player:{packet.Username} PedID:{packet.PedID}");
|
|
|
|
|
}
|
2022-08-10 20:42:47 +08:00
|
|
|
|
|
2022-10-23 19:02:39 +08:00
|
|
|
|
// 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)
|
|
|
|
|
{
|
|
|
|
|
if (newClient == _hostClient) API.SendCustomEvent(new List<Client> { newClient }, CustomEvents.IsHost, true);
|
2022-08-10 20:42:47 +08:00
|
|
|
|
|
2022-10-23 19:02:39 +08:00
|
|
|
|
// Send new client to all players
|
|
|
|
|
var cons = MainNetServer.Connections.Exclude(newClient.Connection);
|
|
|
|
|
if (cons.Count != 0)
|
2022-08-10 20:42:47 +08:00
|
|
|
|
{
|
2022-10-23 19:02:39 +08:00
|
|
|
|
var outgoingMessage = MainNetServer.CreateMessage();
|
|
|
|
|
new Packets.PlayerConnect
|
2022-08-10 20:42:47 +08:00
|
|
|
|
{
|
2022-10-23 19:02:39 +08:00
|
|
|
|
PedID = newClient.Player.ID,
|
|
|
|
|
Username = newClient.Username
|
|
|
|
|
}.Pack(outgoingMessage);
|
2022-08-10 20:42:47 +08:00
|
|
|
|
|
2022-10-23 19:02:39 +08:00
|
|
|
|
MainNetServer.SendMessage(outgoingMessage, cons, NetDeliveryMethod.ReliableOrdered, 0);
|
|
|
|
|
}
|
2022-08-10 20:42:47 +08:00
|
|
|
|
|
2022-10-23 19:02:39 +08:00
|
|
|
|
// Send all props to this player
|
|
|
|
|
BaseScript.SendServerPropsTo(new List<ServerProp>(Entities.ServerProps.Values), new List<Client> { newClient });
|
2022-08-10 20:42:47 +08:00
|
|
|
|
|
2022-10-23 19:02:39 +08:00
|
|
|
|
// Send all blips to this player
|
|
|
|
|
BaseScript.SendServerBlipsTo(new List<ServerBlip>(Entities.Blips.Values), new List<Client> { newClient });
|
2022-08-10 20:42:47 +08:00
|
|
|
|
|
2022-10-23 19:02:39 +08:00
|
|
|
|
// Create P2P connection
|
|
|
|
|
if (Settings.UseP2P)
|
|
|
|
|
ClientsByNetHandle.Values.ForEach(target =>
|
2022-08-10 20:42:47 +08:00
|
|
|
|
{
|
2022-10-23 19:02:39 +08:00
|
|
|
|
if (target == newClient) return;
|
|
|
|
|
HolePunch(target, newClient);
|
|
|
|
|
});
|
2022-08-10 20:42:47 +08:00
|
|
|
|
|
2022-10-23 19:02:39 +08:00
|
|
|
|
Logger?.Info($"Player {newClient.Username} connected!");
|
2022-08-10 20:42:47 +08:00
|
|
|
|
|
2022-10-23 19:02:39 +08:00
|
|
|
|
if (!string.IsNullOrEmpty(Settings.WelcomeMessage))
|
|
|
|
|
SendChatMessage("Server", Settings.WelcomeMessage, newClient);
|
|
|
|
|
}
|
2022-08-10 20:42:47 +08:00
|
|
|
|
|
2022-10-23 19:02:39 +08:00
|
|
|
|
// Send all players a message that someone has left the server
|
|
|
|
|
private void PlayerDisconnected(Client localClient)
|
|
|
|
|
{
|
|
|
|
|
var cons = MainNetServer.Connections.Exclude(localClient.Connection);
|
|
|
|
|
if (cons.Count != 0)
|
2022-08-10 20:42:47 +08:00
|
|
|
|
{
|
2022-10-23 19:02:39 +08:00
|
|
|
|
var outgoingMessage = MainNetServer.CreateMessage();
|
|
|
|
|
new Packets.PlayerDisconnect
|
2022-08-10 20:42:47 +08:00
|
|
|
|
{
|
2022-10-23 19:02:39 +08:00
|
|
|
|
PedID = localClient.Player.ID
|
|
|
|
|
}.Pack(outgoingMessage);
|
|
|
|
|
MainNetServer.SendMessage(outgoingMessage, cons, NetDeliveryMethod.ReliableOrdered, 0);
|
|
|
|
|
}
|
2022-08-10 20:42:47 +08:00
|
|
|
|
|
2022-10-23 19:02:39 +08:00
|
|
|
|
Entities.CleanUp(localClient);
|
|
|
|
|
QueueJob(() => API.Events.InvokePlayerDisconnected(localClient));
|
|
|
|
|
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);
|
|
|
|
|
if (localClient == _hostClient)
|
|
|
|
|
{
|
|
|
|
|
_hostClient = ClientsByNetHandle.Values.FirstOrDefault();
|
|
|
|
|
_hostClient?.SendCustomEvent(CustomEvents.IsHost, true);
|
2022-08-10 20:42:47 +08:00
|
|
|
|
}
|
2022-10-23 19:02:39 +08:00
|
|
|
|
|
|
|
|
|
Security.RemoveConnection(localClient.Connection.RemoteEndPoint);
|
2022-08-10 20:42:47 +08:00
|
|
|
|
}
|
2022-10-23 19:02:39 +08:00
|
|
|
|
}
|