using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Lidgren.Network; using RageCoop.Core; using RageCoop.Core.Scripting; using RageCoop.Server.Scripting; 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() + "]"); if (!packet.ModVersion.StartsWith(_compatibleVersion)) { connection.Deny($"RAGECOOP version {_compatibleVersion.Replace('_', '.')}.x required!"); 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; } 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) { 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; } var handshakeSuccess = MainNetServer.CreateMessage(); var currentClients = ClientsByID.Values.ToArray(); var players = new Packets.PlayerData[currentClients.Length]; for (int i = 0; i { if (target==newClient) { return; } HolePunch(target,newClient); }); } 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); if (cons.Count!=0) { NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage(); new Packets.PlayerDisconnect() { PedID=localClient.Player.ID, }.Pack(outgoingMessage); MainNetServer.SendMessage(outgoingMessage, cons, NetDeliveryMethod.ReliableOrdered, 0); } Entities.CleanUp(localClient); _worker.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); } Security.RemoveConnection(localClient.Connection.RemoteEndPoint); } } }