diff --git a/Barotrauma/BarotraumaClient/Source/DebugConsole.cs b/Barotrauma/BarotraumaClient/Source/DebugConsole.cs index 259dee661..b453ead64 100644 --- a/Barotrauma/BarotraumaClient/Source/DebugConsole.cs +++ b/Barotrauma/BarotraumaClient/Source/DebugConsole.cs @@ -99,15 +99,11 @@ namespace Barotrauma { SelectMessage(1); } - - //textBox.Update(deltaTime); - - if (PlayerInput.KeyDown(Keys.Enter) && textBox.Text != "") + + if (PlayerInput.KeyHit(Keys.Enter)) { ExecuteCommand(textBox.Text, game); textBox.Text = ""; - - //selectedIndex = messages.Count; } } } diff --git a/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs b/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs index df39c4c90..1b9054c8f 100644 --- a/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs +++ b/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs @@ -1241,11 +1241,23 @@ namespace Barotrauma.Networking return true; } - public override void KickPlayer(string kickedName, string reason, bool ban, bool range = false) + public override void KickPlayer(string kickedName, string reason) { NetOutgoingMessage msg = client.CreateMessage(); msg.Write((byte)ClientPacketHeader.SERVER_COMMAND); - msg.Write((byte)(ban ? ClientPermissions.Ban : ClientPermissions.Kick)); + msg.Write((byte)ClientPermissions.Kick); + //TODO: write the reason + msg.Write(kickedName); + + client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered); + } + + public override void BanPlayer(string kickedName, string reason, bool range = false, TimeSpan? duration = null) + { + NetOutgoingMessage msg = client.CreateMessage(); + msg.Write((byte)ClientPacketHeader.SERVER_COMMAND); + msg.Write((byte)ClientPermissions.Ban); + //TODO: write the reason msg.Write(kickedName); client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered); diff --git a/Barotrauma/BarotraumaClient/Source/Networking/NetworkMember.cs b/Barotrauma/BarotraumaClient/Source/Networking/NetworkMember.cs index f1238ba3e..cf13b312c 100644 --- a/Barotrauma/BarotraumaClient/Source/Networking/NetworkMember.cs +++ b/Barotrauma/BarotraumaClient/Source/Networking/NetworkMember.cs @@ -171,7 +171,15 @@ namespace Barotrauma.Networking banReasonPrompt.Buttons[0].OnClicked += (btn, userData) => { - KickPlayer(clientName, textBox.Text, ban, rangeBan); + if (ban) + { + //TODO: a way to set ban duration in the prompt + BanPlayer(clientName, textBox.Text, ban, null); + } + else + { + KickPlayer(clientName, textBox.Text); + } return true; }; banReasonPrompt.Buttons[0].OnClicked += banReasonPrompt.Close; diff --git a/Barotrauma/BarotraumaServer/Source/DebugConsole.cs b/Barotrauma/BarotraumaServer/Source/DebugConsole.cs index 741c25e0f..902a012af 100644 --- a/Barotrauma/BarotraumaServer/Source/DebugConsole.cs +++ b/Barotrauma/BarotraumaServer/Source/DebugConsole.cs @@ -3,9 +3,6 @@ using System.Collections.Generic; using System.Linq; using Microsoft.Xna.Framework; using Barotrauma.Networking; -using Barotrauma.Items.Components; -using System.Text; -using FarseerPhysics; namespace Barotrauma { @@ -31,9 +28,9 @@ namespace Barotrauma { case "restart": case "reset": - DebugConsole.NewMessage("*****************", Color.Lime); - DebugConsole.NewMessage("RESTARTING SERVER", Color.Lime); - DebugConsole.NewMessage("*****************", Color.Lime); + NewMessage("*****************", Color.Lime); + NewMessage("RESTARTING SERVER", Color.Lime); + NewMessage("*****************", Color.Lime); GameMain.Instance.CloseServer(); GameMain.Instance.StartServer(); break; @@ -69,7 +66,7 @@ namespace Barotrauma { GameMain.NetLobbyScreen.SelectedModeName = string.Join(" ", commands.Skip(1)); } - DebugConsole.NewMessage("Set gamemode to " + GameMain.NetLobbyScreen.SelectedModeName, Color.Cyan); + NewMessage("Set gamemode to " + GameMain.NetLobbyScreen.SelectedModeName, Color.Cyan); } break; case "mission": @@ -83,7 +80,7 @@ namespace Barotrauma { GameMain.NetLobbyScreen.MissionTypeName = string.Join(" ", commands.Skip(1)); } - DebugConsole.NewMessage("Set mission to " + GameMain.NetLobbyScreen.MissionTypeName, Color.Cyan); + NewMessage("Set mission to " + GameMain.NetLobbyScreen.MissionTypeName, Color.Cyan); } break; case "sub": @@ -96,7 +93,7 @@ namespace Barotrauma GameMain.NetLobbyScreen.SelectedSub = sub; } sub = GameMain.NetLobbyScreen.SelectedSub; - DebugConsole.NewMessage("Selected sub: " + sub.Name + (sub.HasTag(SubmarineTag.Shuttle) ? " (shuttle)" : ""), Color.Cyan); + NewMessage("Selected sub: " + sub.Name + (sub.HasTag(SubmarineTag.Shuttle) ? " (shuttle)" : ""), Color.Cyan); } break; case "shuttle": @@ -108,7 +105,7 @@ namespace Barotrauma GameMain.NetLobbyScreen.SelectedShuttle = shuttle; } shuttle = GameMain.NetLobbyScreen.SelectedShuttle; - DebugConsole.NewMessage("Selected shuttle: " + shuttle.Name + (shuttle.HasTag(SubmarineTag.Shuttle) ? "" : " (not shuttle)"), Color.Cyan); + NewMessage("Selected shuttle: " + shuttle.Name + (shuttle.HasTag(SubmarineTag.Shuttle) ? "" : " (not shuttle)"), Color.Cyan); } break; case "startgame": diff --git a/Barotrauma/BarotraumaShared/Source/DebugConsole.cs b/Barotrauma/BarotraumaShared/Source/DebugConsole.cs index fe4e90db8..2a005af27 100644 --- a/Barotrauma/BarotraumaShared/Source/DebugConsole.cs +++ b/Barotrauma/BarotraumaShared/Source/DebugConsole.cs @@ -34,7 +34,9 @@ namespace Barotrauma private delegate void QuestionCallback(string answer); private static QuestionCallback activeQuestionCallback; +#if CLIENT private static GUIComponent activeQuestionText; +#endif private static string[] SplitCommand(string command) { @@ -74,16 +76,21 @@ namespace Barotrauma public static void ExecuteCommand(string command, GameMain game) { - if (string.IsNullOrWhiteSpace(command)) return; - if (activeQuestionCallback != null) { +#if CLIENT activeQuestionText = null; - activeQuestionCallback(command); - activeQuestionCallback = null; +#endif + NewMessage(command, Color.White); + //reset the variable before invoking the delegate because the method may need to activate another question + var temp = activeQuestionCallback; + activeQuestionCallback = null; + temp(command); return; } + if (string.IsNullOrWhiteSpace(command)) return; + string[] commands = SplitCommand(command); if (!commands[0].ToLowerInvariant().Equals("admin")) @@ -91,26 +98,24 @@ namespace Barotrauma NewMessage(command, Color.White); } -#if !DEBUG -#if CLIENT +#if !DEBUG && CLIENT if (GameMain.Client != null && !IsCommandPermitted(commands[0].ToLowerInvariant(), GameMain.Client)) { ThrowError("You're not permitted to use the command \"" + commands[0].ToLowerInvariant()+"\"!"); return; } -#endif #endif switch (commands[0].ToLowerInvariant()) { case "clientlist": if (GameMain.Server == null) break; - DebugConsole.NewMessage("***************", Color.Cyan); + NewMessage("***************", Color.Cyan); foreach (Client c in GameMain.Server.ConnectedClients) { - DebugConsole.NewMessage("- " + c.ID.ToString() + ": " + c.name + ", " + c.Connection.RemoteEndPoint.Address.ToString(), Color.Cyan); + NewMessage("- " + c.ID.ToString() + ": " + c.name + ", " + c.Connection.RemoteEndPoint.Address.ToString(), Color.Cyan); } - DebugConsole.NewMessage("***************", Color.Cyan); + NewMessage("***************", Color.Cyan); break; case "help": NewMessage("menu: go to main menu", Color.Cyan); @@ -319,9 +324,9 @@ namespace Barotrauma { string playerName = string.Join(" ", commands.Skip(1)); - ShowQuestionPrompt("Reason for kicking \"" + playerName + "\"?", (answer) => + ShowQuestionPrompt("Reason for kicking \"" + playerName + "\"?", (reason) => { - GameMain.NetworkMember.KickPlayer(playerName, answer, false); + GameMain.NetworkMember.KickPlayer(playerName, reason); }); } break; @@ -340,9 +345,31 @@ namespace Barotrauma return; } - ShowQuestionPrompt(ban ? "Reason for banning \"" + client.name + "\"?" : "Reason for kicking \"" + client.name + "\"?", (answer) => + ShowQuestionPrompt(ban ? "Reason for banning \"" + client.name + "\"?" : "Reason for kicking \"" + client.name + "\"?", (reason) => { - GameMain.Server.KickPlayer(client.name, answer, ban); + if (ban) + { + ShowQuestionPrompt("Enter the duration of the ban (leave empty to ban permanently, or use the format \"[days] d [hours] h\")", (duration) => + { + TimeSpan? banDuration = null; + if (!string.IsNullOrWhiteSpace(duration)) + { + TimeSpan parsedBanDuration; + if (!TryParseTimeSpan(duration, out parsedBanDuration)) + { + ThrowError("\"" + duration + "\" is not a valid ban duration. Use the format \"[days] d [hours] h\", \"[days] d\" or \"[hours] h\"."); + return; + } + banDuration = parsedBanDuration; + } + + GameMain.Server.BanPlayer(client.name, reason, false, banDuration); + }); + } + else + { + GameMain.Server.KickPlayer(client.name, reason); + } }); } break; @@ -350,26 +377,56 @@ namespace Barotrauma if (GameMain.NetworkMember != null || commands.Length >= 2) { string clientName = string.Join(" ", commands.Skip(1)); - ShowQuestionPrompt("Reason for banning \"" + clientName + "\"?", (answer) => + ShowQuestionPrompt("Reason for banning \"" + clientName + "\"?", (reason) => { - GameMain.NetworkMember.KickPlayer(clientName, answer, true); + ShowQuestionPrompt("Enter the duration of the ban (leave empty to ban permanently, or use the format \"[days] d [hours] h\")", (duration) => + { + TimeSpan? banDuration = null; + if (!string.IsNullOrWhiteSpace(duration)) + { + TimeSpan parsedBanDuration; + if (!TryParseTimeSpan(duration, out parsedBanDuration)) + { + ThrowError("\"" + duration + "\" is not a valid ban duration. Use the format \"[days] d [hours] h\", \"[days] d\" or \"[hours] h\"."); + return; + } + banDuration = parsedBanDuration; + } + + GameMain.NetworkMember.BanPlayer(clientName, reason, false, banDuration); + }); }); } break; case "banip": if (GameMain.Server != null || commands.Length >= 2) { - ShowQuestionPrompt("Reason for banning the ip \"" + commands[1] + "\"?", (answer) => + ShowQuestionPrompt("Reason for banning the ip \"" + commands[1] + "\"?", (reason) => { - var client = GameMain.Server.ConnectedClients.Find(c => c.Connection.RemoteEndPoint.Address.ToString() == commands[1]); - if (client == null) + ShowQuestionPrompt("Enter the duration of the ban (leave empty to ban permanently, or use the format \"[days] d [hours] h\")", (duration) => { - GameMain.Server.BanList.BanPlayer("Unnamed", commands[1], answer); - } - else - { - GameMain.Server.KickClient(client, answer, true); - } + TimeSpan? banDuration = null; + if (!string.IsNullOrWhiteSpace(duration)) + { + TimeSpan parsedBanDuration; + if (!TryParseTimeSpan(duration, out parsedBanDuration)) + { + ThrowError("\""+duration+ "\" is not a valid ban duration. Use the format \"[days] d [hours] h\", \"[days] d\" or \"[hours] h\"."); + return; + } + banDuration = parsedBanDuration; + } + + var client = GameMain.Server.ConnectedClients.Find(c => c.Connection.RemoteEndPoint.Address.ToString() == commands[1]); + if (client == null) + { + GameMain.Server.BanList.BanPlayer("Unnamed", commands[1], reason, banDuration); + } + else + { + GameMain.Server.KickClient(client, reason); + } + }); }); } break; @@ -655,10 +712,61 @@ namespace Barotrauma { NewMessage(" >>" + question, Color.Cyan); activeQuestionCallback += onAnswered; +#if CLIENT if (listBox != null && listBox.children.Count > 0) { activeQuestionText = listBox.children[listBox.children.Count - 1]; } +#endif + } + + private static bool TryParseTimeSpan(string s, out TimeSpan timeSpan) + { + timeSpan = new TimeSpan(); + if (string.IsNullOrWhiteSpace(s)) return false; + + string currNum = ""; + foreach (char c in s) + { + if (char.IsDigit(c)) + { + currNum += c; + } + else if (char.IsWhiteSpace(c)) + { + continue; + } + else + { + int parsedNum = 0; + if (!int.TryParse(currNum, out parsedNum)) + { + return false; + } + + switch (c) + { + case 'd': + timeSpan += new TimeSpan(parsedNum, 0, 0, 0, 0); + break; + case 'h': + timeSpan += new TimeSpan(0, parsedNum, 0, 0, 0); + break; + case 'm': + timeSpan += new TimeSpan(0, 0, parsedNum, 0, 0); + break; + case 's': + timeSpan += new TimeSpan(0, 0, 0, parsedNum, 0); + break; + default: + return false; + } + + currNum = ""; + } + } + + return true; } diff --git a/Barotrauma/BarotraumaShared/Source/Networking/BanList.cs b/Barotrauma/BarotraumaShared/Source/Networking/BanList.cs index 6f9691aad..c610b307e 100644 --- a/Barotrauma/BarotraumaShared/Source/Networking/BanList.cs +++ b/Barotrauma/BarotraumaShared/Source/Networking/BanList.cs @@ -11,6 +11,7 @@ namespace Barotrauma.Networking public string Name; public string IP; public string Reason; + public DateTime? ExpirationTime; public bool CompareTo(string ipCompare) { @@ -26,11 +27,12 @@ namespace Barotrauma.Networking } } - public BannedPlayer(string name, string ip, string reason) + public BannedPlayer(string name, string ip, string reason, DateTime? expirationTime) { this.Name = name; this.IP = ip; this.Reason = reason; + this.ExpirationTime = expirationTime; } } @@ -64,14 +66,26 @@ namespace Barotrauma.Networking string name = separatedLine[0]; string ip = separatedLine[1]; - string reason = separatedLine.Length > 2 ? string.Join(",", separatedLine.Skip(2)) : ""; - bannedPlayers.Add(new BannedPlayer(name, ip,reason)); + DateTime? expirationTime = DateTime.Now; + if (separatedLine.Length > 2) + { + DateTime parsedTime; + if (DateTime.TryParse(separatedLine[2], out parsedTime)) + { + expirationTime = parsedTime; + } + } + string reason = separatedLine.Length > 3 ? string.Join(",", separatedLine.Skip(3)) : ""; + + if (expirationTime.HasValue && expirationTime.Value > DateTime.Now) continue; + + bannedPlayers.Add(new BannedPlayer(name, ip, reason, expirationTime)); } } } - public void BanPlayer(string name, string ip, string reason) + public void BanPlayer(string name, string ip, string reason, TimeSpan? duration) { if (bannedPlayers.Any(bp => bp.IP == ip)) return; @@ -79,12 +93,19 @@ namespace Barotrauma.Networking DebugConsole.Log("Banned " + name); - bannedPlayers.Add(new BannedPlayer(name, ip, reason)); + DateTime? expirationTime = null; + if (duration.HasValue) + { + expirationTime = DateTime.Now + duration.Value; + } + + bannedPlayers.Add(new BannedPlayer(name, ip, reason, expirationTime)); Save(); } public bool IsBanned(string IP) { + bannedPlayers.RemoveAll(bp => bp.ExpirationTime.HasValue && DateTime.Now > bp.ExpirationTime.Value); return bannedPlayers.Any(bp => bp.CompareTo(IP)); } @@ -131,12 +152,15 @@ namespace Barotrauma.Networking { GameServer.Log("Saving banlist", ServerLog.MessageType.ServerMessage); - List lines = new List(); + bannedPlayers.RemoveAll(bp => bp.ExpirationTime.HasValue && DateTime.Now > bp.ExpirationTime.Value); + List lines = new List(); foreach (BannedPlayer banned in bannedPlayers) { string line = banned.Name + "," + banned.IP; + if (banned.ExpirationTime.HasValue) line += "," + banned.ExpirationTime.Value.ToString(); if (!string.IsNullOrWhiteSpace(banned.Reason)) line += "," + banned.Reason; + lines.Add(line); } diff --git a/Barotrauma/BarotraumaShared/Source/Networking/GameServer.cs b/Barotrauma/BarotraumaShared/Source/Networking/GameServer.cs index bf32a3ef9..04b77aa1c 100644 --- a/Barotrauma/BarotraumaShared/Source/Networking/GameServer.cs +++ b/Barotrauma/BarotraumaShared/Source/Networking/GameServer.cs @@ -531,7 +531,7 @@ namespace Barotrauma.Networking { if (banList.IsBanned(inc.SenderEndPoint.Address.ToString())) { - KickClient(inc.SenderConnection, "You have been banned from the server.", true); + KickClient(inc.SenderConnection, "You have been banned from the server."); return; } @@ -759,7 +759,7 @@ namespace Barotrauma.Networking if (kickedClient != null) { Log("Client \"" + sender.name + "\" kicked \"" + kickedClient.name + "\".", ServerLog.MessageType.ServerMessage); - KickClient(kickedClient, "Kicked by " + sender.name, false, false); + KickClient(kickedClient, "Kicked by " + sender.name); } break; case ClientPermissions.Ban: @@ -768,7 +768,7 @@ namespace Barotrauma.Networking if (bannedClient != null) { Log("Client \"" + sender.name + "\" banned \"" + bannedClient.name + "\".", ServerLog.MessageType.ServerMessage); - KickClient(bannedClient, "Banned by " + sender.name, true, false); + BanClient(bannedClient, "Banned by " + sender.name, false); } break; case ClientPermissions.EndRound: @@ -809,6 +809,11 @@ namespace Barotrauma.Networking /// private void ClientWriteInitial(Client c, NetBuffer outmsg) { + if (GameSettings.VerboseLogging) + { + DebugConsole.NewMessage("Sending initial lobby update", Color.Gray); + } + outmsg.Write(c.ID); var subList = GameMain.NetLobbyScreen.GetSubList(); @@ -1416,7 +1421,7 @@ namespace Barotrauma.Networking yield return CoroutineStatus.Success; } - public override void KickPlayer(string playerName, string reason, bool ban, bool range = false) + public override void KickPlayer(string playerName, string reason) { playerName = playerName.ToLowerInvariant(); @@ -1424,48 +1429,68 @@ namespace Barotrauma.Networking c.name.ToLowerInvariant() == playerName || (c.Character != null && c.Character.Name.ToLowerInvariant() == playerName)); - KickClient(client, reason, ban, range); + KickClient(client, reason); } - public void KickClient(NetConnection conn, string reason, bool ban = false, bool range = false) + public void KickClient(NetConnection conn, string reason) + { + Client client = connectedClients.Find(c => c.Connection == conn); + KickClient(client, reason); + } + + public void KickClient(Client client, string reason) + { + if (client == null) return; + + string msg = "You have been kicked from the server."; + if (!string.IsNullOrWhiteSpace(reason)) msg += "\nReason: " + reason; + DisconnectClient(client, client.name + " has been kicked from the server.", msg); + } + + public override void BanPlayer(string playerName, string reason, bool range = false, TimeSpan? duration = null) + { + playerName = playerName.ToLowerInvariant(); + + Client client = connectedClients.Find(c => + c.name.ToLowerInvariant() == playerName || + (c.Character != null && c.Character.Name.ToLowerInvariant() == playerName)); + + if (client == null) + { + DebugConsole.ThrowError("Client \"" + playerName + "\" not found."); + return; + } + + BanClient(client, reason, range, duration); + } + + public void BanClient(NetConnection conn, string reason, bool range = false, TimeSpan? duration = null) { Client client = connectedClients.Find(c => c.Connection == conn); if (client == null) { - conn.Disconnect(ban ? "You have been banned from the server" : "You have been kicked from the server"); - if (ban) + conn.Disconnect("You have been banned from the server"); + if (!banList.IsBanned(conn.RemoteEndPoint.Address.ToString())) { - if (!banList.IsBanned(conn.RemoteEndPoint.Address.ToString())) - { - banList.BanPlayer("Unnamed", conn.RemoteEndPoint.Address.ToString(), reason); - } - } + banList.BanPlayer("Unnamed", conn.RemoteEndPoint.Address.ToString(), reason, duration); + } } else { - KickClient(client, reason, ban, range); + BanClient(client, reason, range); } } - public void KickClient(Client client, string reason, bool ban = false, bool range = false) + public void BanClient(Client client, string reason, bool range = false, TimeSpan? duration = null) { if (client == null) return; - - if (ban) - { - string msg = "You have been banned from the server."; - if (!string.IsNullOrWhiteSpace(reason)) msg += "\nReason: " + reason; - DisconnectClient(client, client.name + " has been banned from the server.", msg); - string ip = client.Connection.RemoteEndPoint.Address.ToString(); - if (range) { ip = banList.ToRange(ip); } - banList.BanPlayer(client.name, ip, reason); - } - else - { - string msg = "You have been kicked from the server."; - if (!string.IsNullOrWhiteSpace(reason)) msg += "\nReason: " + reason; - DisconnectClient(client, client.name + " has been kicked from the server.", msg); - } + + string msg = "You have been banned from the server."; + if (!string.IsNullOrWhiteSpace(reason)) msg += "\nReason: " + reason; + DisconnectClient(client, client.name + " has been banned from the server.", msg); + string ip = client.Connection.RemoteEndPoint.Address.ToString(); + if (range) { ip = banList.ToRange(ip); } + banList.BanPlayer(client.name, ip, reason, duration); } public void DisconnectClient(NetConnection senderConnection, string msg = "", string targetmsg = "") diff --git a/Barotrauma/BarotraumaShared/Source/Networking/GameServerLogin.cs b/Barotrauma/BarotraumaShared/Source/Networking/GameServerLogin.cs index fc31f0e02..746ad4b9b 100644 --- a/Barotrauma/BarotraumaShared/Source/Networking/GameServerLogin.cs +++ b/Barotrauma/BarotraumaShared/Source/Networking/GameServerLogin.cs @@ -102,7 +102,7 @@ namespace Barotrauma.Networking if (unauthClient.failedAttempts > 3) { //disconnect and ban after too many failed attempts - banList.BanPlayer("Unnamed", unauthClient.Connection.RemoteEndPoint.Address.ToString(), "Too many failed login attempts."); + banList.BanPlayer("Unnamed", unauthClient.Connection.RemoteEndPoint.Address.ToString(), "Too many failed login attempts.", null); DisconnectUnauthClient(inc, unauthClient, "Too many failed login attempts. You have been automatically banned from the server."); Log(inc.SenderConnection.RemoteEndPoint.Address.ToString() + " has been banned from the server (too many wrong passwords)", ServerLog.MessageType.Error); diff --git a/Barotrauma/BarotraumaShared/Source/Networking/NetworkMember.cs b/Barotrauma/BarotraumaShared/Source/Networking/NetworkMember.cs index 6d6344049..64cb11e6e 100644 --- a/Barotrauma/BarotraumaShared/Source/Networking/NetworkMember.cs +++ b/Barotrauma/BarotraumaShared/Source/Networking/NetworkMember.cs @@ -191,7 +191,9 @@ namespace Barotrauma.Networking #endif } - public virtual void KickPlayer(string kickedName, string reason, bool ban, bool range = false) { } + public virtual void KickPlayer(string kickedName, string reason) { } + + public virtual void BanPlayer(string kickedName, string reason, bool range = false, TimeSpan? duration = null) { } public virtual void Update(float deltaTime) {