From da71b6bf9c82fb3874d4599fedcbe93677c06acd Mon Sep 17 00:00:00 2001 From: Joonas Rikkonen Date: Sun, 2 Jul 2017 15:25:55 +0300 Subject: [PATCH] Option to supply a reason for banning/kicking, logic for handling question prompts in the debug console --- .../Source/Networking/BanList.cs | 1 + .../Source/Networking/GameClient.cs | 35 ++--- .../Source/Networking/NetworkMember.cs | 15 ++ .../Source/Screens/NetLobbyScreen.cs | 39 +---- .../BarotraumaServer/Source/DebugConsole.cs | 1 - .../BarotraumaShared/Source/DebugConsole.cs | 143 ++++++++++++------ .../Source/Networking/BanList.cs | 24 +-- .../Source/Networking/ChatMessage.cs | 2 +- .../Source/Networking/GameServer.cs | 63 ++++---- .../Source/Networking/GameServerLogin.cs | 2 +- .../Source/Networking/NetworkMember.cs | 2 +- 11 files changed, 185 insertions(+), 142 deletions(-) diff --git a/Barotrauma/BarotraumaClient/Source/Networking/BanList.cs b/Barotrauma/BarotraumaClient/Source/Networking/BanList.cs index fc43b01bc..7e7640176 100644 --- a/Barotrauma/BarotraumaClient/Source/Networking/BanList.cs +++ b/Barotrauma/BarotraumaClient/Source/Networking/BanList.cs @@ -29,6 +29,7 @@ namespace Barotrauma.Networking Alignment.Left, Alignment.Left, banFrame); textBlock.Padding = new Vector4(10.0f, 10.0f, 0.0f, 0.0f); textBlock.UserData = banFrame; + textBlock.ToolTip = bannedPlayer.Reason; var removeButton = new GUIButton(new Rectangle(0, 0, 100, 20), "Remove", Alignment.Right | Alignment.CenterY, "", textBlock); removeButton.UserData = bannedPlayer; diff --git a/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs b/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs index 31e8be477..df39c4c90 100644 --- a/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs +++ b/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs @@ -565,26 +565,23 @@ namespace Barotrauma.Networking { string disconnectMsg = inc.ReadString(); - switch (disconnectMsg) + if (disconnectMsg.Contains("You have been disconnected") || + disconnectMsg.Contains("You have been banned") || + disconnectMsg.Contains("You have been kicked") || + disconnectMsg == "The server has been shut down") { - case "The server has been shut down": - case "You have been banned from the server": - case "You have been kicked from the server": - case "You have been disconnected because of excessive desync": - case "You have been disconnected because syncing your client with the server took too long.": - var msgBox = new GUIMessageBox("CONNECTION LOST", disconnectMsg); - msgBox.Buttons[0].OnClicked += ReturnToServerList; - break; - default: - reconnectBox = new GUIMessageBox( - "CONNECTION LOST", - "You have been disconnected from the server. Reconnecting...", new string[0]); - - connected = false; - ConnectToServer(serverIP); - break; + var msgBox = new GUIMessageBox("CONNECTION LOST", disconnectMsg); + msgBox.Buttons[0].OnClicked += ReturnToServerList; + } + else + { + reconnectBox = new GUIMessageBox( + "CONNECTION LOST", + "You have been disconnected from the server. Reconnecting...", new string[0]); + + connected = false; + ConnectToServer(serverIP); } - } break; } @@ -1244,7 +1241,7 @@ namespace Barotrauma.Networking return true; } - public override void KickPlayer(string kickedName, bool ban, bool range = false) + public override void KickPlayer(string kickedName, string reason, bool ban, bool range = false) { NetOutgoingMessage msg = client.CreateMessage(); msg.Write((byte)ClientPacketHeader.SERVER_COMMAND); diff --git a/Barotrauma/BarotraumaClient/Source/Networking/NetworkMember.cs b/Barotrauma/BarotraumaClient/Source/Networking/NetworkMember.cs index 6ec1fede1..f1238ba3e 100644 --- a/Barotrauma/BarotraumaClient/Source/Networking/NetworkMember.cs +++ b/Barotrauma/BarotraumaClient/Source/Networking/NetworkMember.cs @@ -161,5 +161,20 @@ namespace Barotrauma.Networking { return false; } + + public void CreateKickReasonPrompt(string clientName, bool ban, bool rangeBan = false) + { + var banReasonPrompt = new GUIMessageBox(ban ? "Reason for the ban?" : "Reason for kicking?", "", new string[] { "OK" }, 400, 250); + var textBox = new GUITextBox(new Rectangle(0, 0, 0, 50), Alignment.Center, "", banReasonPrompt.children[0]); + textBox.Wrap = true; + textBox.MaxTextLength = 100; + + banReasonPrompt.Buttons[0].OnClicked += (btn, userData) => + { + KickPlayer(clientName, textBox.Text, ban, rangeBan); + return true; + }; + banReasonPrompt.Buttons[0].OnClicked += banReasonPrompt.Close; + } } } diff --git a/Barotrauma/BarotraumaClient/Source/Screens/NetLobbyScreen.cs b/Barotrauma/BarotraumaClient/Source/Screens/NetLobbyScreen.cs index 4734b8d59..b658a9330 100644 --- a/Barotrauma/BarotraumaClient/Source/Screens/NetLobbyScreen.cs +++ b/Barotrauma/BarotraumaClient/Source/Screens/NetLobbyScreen.cs @@ -893,49 +893,22 @@ namespace Barotrauma public bool KickPlayer(GUIButton button, object userData) { - if (userData == null) return false; - - if (GameMain.Server != null) - { - GameMain.Server.KickPlayer(userData.ToString(), false); - } - else if (GameMain.Client != null && GameMain.Client.HasPermission(ClientPermissions.Kick)) - { - GameMain.Client.KickPlayer(userData.ToString(), false); - } - + if (userData == null || GameMain.NetworkMember == null) return false; + GameMain.NetworkMember.CreateKickReasonPrompt(userData.ToString(), false); return false; } public bool BanPlayer(GUIButton button, object userData) { - if (userData == null) return false; - - if (GameMain.Server != null) - { - GameMain.Server.KickPlayer(userData.ToString(), true); - } - else if (GameMain.Client != null && GameMain.Client.HasPermission(ClientPermissions.Ban)) - { - GameMain.Client.KickPlayer(userData.ToString(), true); - } - + if (userData == null || GameMain.NetworkMember == null) return false; + GameMain.NetworkMember.CreateKickReasonPrompt(userData.ToString(), true); return false; } public bool BanPlayerRange(GUIButton button, object userData) { - if (userData == null) return false; - - if (GameMain.Server != null) - { - GameMain.Server.KickPlayer(userData.ToString(), true, true); - } - else if (GameMain.Client != null && GameMain.Client.HasPermission(ClientPermissions.Ban)) - { - GameMain.Client.KickPlayer(userData.ToString(), true, true); - } - + if (userData == null || GameMain.NetworkMember == null) return false; + GameMain.NetworkMember.CreateKickReasonPrompt(userData.ToString(), true, true); return false; } diff --git a/Barotrauma/BarotraumaServer/Source/DebugConsole.cs b/Barotrauma/BarotraumaServer/Source/DebugConsole.cs index 9ca53c56f..741c25e0f 100644 --- a/Barotrauma/BarotraumaServer/Source/DebugConsole.cs +++ b/Barotrauma/BarotraumaServer/Source/DebugConsole.cs @@ -141,7 +141,6 @@ namespace Barotrauma #endif default: return false; - break; } return true; //command found } diff --git a/Barotrauma/BarotraumaShared/Source/DebugConsole.cs b/Barotrauma/BarotraumaShared/Source/DebugConsole.cs index bd3d5ae5e..fe4e90db8 100644 --- a/Barotrauma/BarotraumaShared/Source/DebugConsole.cs +++ b/Barotrauma/BarotraumaShared/Source/DebugConsole.cs @@ -32,6 +32,10 @@ namespace Barotrauma public static List Messages = new List(); + private delegate void QuestionCallback(string answer); + private static QuestionCallback activeQuestionCallback; + private static GUIComponent activeQuestionText; + private static string[] SplitCommand(string command) { command = command.Trim(); @@ -41,7 +45,7 @@ namespace Barotrauma bool inQuotes = false; string piece = ""; - for (int i=0;i ip.Name.ToLowerInvariant() == itemName) as ItemPrefab; if (itemPrefab == null) { - ThrowError("Item \""+itemName+"\" not found!"); + ThrowError("Item \"" + itemName + "\" not found!"); return; } @@ -302,48 +315,63 @@ namespace Barotrauma } break;*/ case "kick": - if (GameMain.NetworkMember == null || commands.Length < 2) break; - GameMain.NetworkMember.KickPlayer(string.Join(" ", commands.Skip(1)), false); + if (GameMain.NetworkMember != null && commands.Length >= 2) + { + string playerName = string.Join(" ", commands.Skip(1)); + ShowQuestionPrompt("Reason for kicking \"" + playerName + "\"?", (answer) => + { + GameMain.NetworkMember.KickPlayer(playerName, answer, false); + }); + } break; case "kickid": - if (GameMain.Server == null || commands.Length < 2) break; - - { - int id = 0; - int.TryParse(commands[1], out id); - GameMain.Server.KickPlayer(id, false); - } - break; case "banid": - if (GameMain.Server == null || commands.Length < 2) break; - + if (GameMain.Server != null && commands.Length >= 2) { + bool ban = commands[0].ToLowerInvariant() == "banid"; + int id = 0; int.TryParse(commands[1], out id); - GameMain.Server.KickPlayer(id, true); - } - - break; - case "ban": - if (GameMain.NetworkMember == null || commands.Length < 2) break; - GameMain.NetworkMember.KickPlayer(string.Join(" ", commands.Skip(1)), true); - - break; - case "banip": - { - if (GameMain.Server == null || commands.Length < 2) break; - - var client = GameMain.Server.ConnectedClients.Find(c => c.Connection.RemoteEndPoint.Address.ToString() == commands[1]); + var client = GameMain.Server.ConnectedClients.Find(c => c.ID == id); if (client == null) { - GameMain.Server.BanList.BanPlayer("Unnamed", commands[1]); + ThrowError("Client id \"" + id + "\" not found."); + return; } - else + + ShowQuestionPrompt(ban ? "Reason for banning \"" + client.name + "\"?" : "Reason for kicking \"" + client.name + "\"?", (answer) => { - GameMain.Server.KickClient(client, true); - } - } + GameMain.Server.KickPlayer(client.name, answer, ban); + }); + } + break; + case "ban": + if (GameMain.NetworkMember != null || commands.Length >= 2) + { + string clientName = string.Join(" ", commands.Skip(1)); + ShowQuestionPrompt("Reason for banning \"" + clientName + "\"?", (answer) => + { + GameMain.NetworkMember.KickPlayer(clientName, answer, true); + }); + } + break; + case "banip": + if (GameMain.Server != null || commands.Length >= 2) + { + ShowQuestionPrompt("Reason for banning the ip \"" + commands[1] + "\"?", (answer) => + { + var client = GameMain.Server.ConnectedClients.Find(c => c.Connection.RemoteEndPoint.Address.ToString() == commands[1]); + if (client == null) + { + GameMain.Server.BanList.BanPlayer("Unnamed", commands[1], answer); + } + else + { + GameMain.Server.KickClient(client, answer, true); + } + }); + } break; case "teleportcharacter": case "teleport": @@ -367,6 +395,7 @@ namespace Barotrauma if (Submarine.MainSub == null) return; Submarine.MainSub.GodMode = !Submarine.MainSub.GodMode; + NewMessage(Submarine.MainSub.GodMode ? "Godmode on" : "Godmode off", Color.White); break; case "lockx": Submarine.LockX = !Submarine.LockX; @@ -441,8 +470,12 @@ namespace Barotrauma break; case "editwater": case "water": - if (GameMain.Client == null) Hull.EditWater = !Hull.EditWater; - + if (GameMain.Client == null) + { + Hull.EditWater = !Hull.EditWater; + NewMessage(Hull.EditWater ? "Water editing on" : "Water editing off", Color.White); + } + break; case "explosion": Vector2 explosionPos = GameMain.GameScreen.Cam.ScreenToWorld(PlayerInput.MousePosition); @@ -453,7 +486,11 @@ namespace Barotrauma new Explosion(range, force, damage, damage).Explode(explosionPos); break; case "fire": - if (GameMain.Client == null) Hull.EditFire = !Hull.EditFire; + if (GameMain.Client == null) + { + Hull.EditFire = !Hull.EditFire; + NewMessage(Hull.EditWater ? "Fire spawning on" : "Fire spawning off", Color.White); + } break; case "fixitems": @@ -604,9 +641,27 @@ namespace Barotrauma } selectedIndex = listBox.children.Count; + + if (activeQuestionText != null) + { + //make sure the active question stays at the bottom of the list + listBox.children.Remove(activeQuestionText); + listBox.children.Add(activeQuestionText); + } #endif } + private static void ShowQuestionPrompt(string question, QuestionCallback onAnswered) + { + NewMessage(" >>" + question, Color.Cyan); + activeQuestionCallback += onAnswered; + if (listBox != null && listBox.children.Count > 0) + { + activeQuestionText = listBox.children[listBox.children.Count - 1]; + } + } + + public static void Log(string message) { if (GameSettings.VerboseLogging) NewMessage(message, Color.Gray); diff --git a/Barotrauma/BarotraumaShared/Source/Networking/BanList.cs b/Barotrauma/BarotraumaShared/Source/Networking/BanList.cs index 3e1147ddf..6f9691aad 100644 --- a/Barotrauma/BarotraumaShared/Source/Networking/BanList.cs +++ b/Barotrauma/BarotraumaShared/Source/Networking/BanList.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; -using System.Text; namespace Barotrauma.Networking { @@ -11,11 +10,12 @@ namespace Barotrauma.Networking { public string Name; public string IP; + public string Reason; public bool CompareTo(string ipCompare) { int rangeBanIndex = IP.IndexOf(".x"); - if (rangeBanIndex<=-1) + if (rangeBanIndex <= -1) { return ipCompare == IP; } @@ -26,10 +26,11 @@ namespace Barotrauma.Networking } } - public BannedPlayer(string name, string ip) + public BannedPlayer(string name, string ip, string reason) { this.Name = name; this.IP = ip; + this.Reason = reason; } } @@ -61,21 +62,24 @@ namespace Barotrauma.Networking string[] separatedLine = line.Split(','); if (separatedLine.Length < 2) continue; - string name = String.Join(",", separatedLine.Take(separatedLine.Length - 1)); - string ip = separatedLine.Last(); + string name = separatedLine[0]; + string ip = separatedLine[1]; + string reason = separatedLine.Length > 2 ? string.Join(",", separatedLine.Skip(2)) : ""; - bannedPlayers.Add(new BannedPlayer(name, ip)); + bannedPlayers.Add(new BannedPlayer(name, ip,reason)); } } } - public void BanPlayer(string name, string ip) + public void BanPlayer(string name, string ip, string reason) { if (bannedPlayers.Any(bp => bp.IP == ip)) return; + System.Diagnostics.Debug.Assert(!name.Contains(',')); + DebugConsole.Log("Banned " + name); - bannedPlayers.Add(new BannedPlayer(name, ip)); + bannedPlayers.Add(new BannedPlayer(name, ip, reason)); Save(); } @@ -131,7 +135,9 @@ namespace Barotrauma.Networking foreach (BannedPlayer banned in bannedPlayers) { - lines.Add(banned.Name + "," + banned.IP); + string line = banned.Name + "," + banned.IP; + if (!string.IsNullOrWhiteSpace(banned.Reason)) line += "," + banned.Reason; + lines.Add(line); } try diff --git a/Barotrauma/BarotraumaShared/Source/Networking/ChatMessage.cs b/Barotrauma/BarotraumaShared/Source/Networking/ChatMessage.cs index fd448eb22..828a8cca9 100644 --- a/Barotrauma/BarotraumaShared/Source/Networking/ChatMessage.cs +++ b/Barotrauma/BarotraumaShared/Source/Networking/ChatMessage.cs @@ -172,7 +172,7 @@ namespace Barotrauma.Networking if (c.ChatSpamCount > 3) { //kick for spamming too much - GameMain.Server.KickClient(c); + GameMain.Server.KickClient(c, "You have been kicked by the spam filter."); } else { diff --git a/Barotrauma/BarotraumaShared/Source/Networking/GameServer.cs b/Barotrauma/BarotraumaShared/Source/Networking/GameServer.cs index 3bce7748f..bf32a3ef9 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, true); + KickClient(inc.SenderConnection, "You have been banned from the server.", true); return; } @@ -727,8 +727,8 @@ namespace Barotrauma.Networking private void ClientReadServerCommand(NetIncomingMessage inc) { - Client c = ConnectedClients.Find(x => x.Connection == inc.SenderConnection); - if (c == null) + Client sender = ConnectedClients.Find(x => x.Connection == inc.SenderConnection); + if (sender == null) { inc.SenderConnection.Disconnect("You're not a connected client."); return; @@ -745,9 +745,9 @@ namespace Barotrauma.Networking return; } - if (!c.HasPermission(command)) + if (!sender.HasPermission(command)) { - Log("Client \""+c.name+"\" sent a server command \""+command+"\". Permission denied.", ServerLog.MessageType.ServerMessage); + Log("Client \""+sender.name+"\" sent a server command \""+command+"\". Permission denied.", ServerLog.MessageType.ServerMessage); return; } @@ -755,26 +755,26 @@ namespace Barotrauma.Networking { case ClientPermissions.Kick: string kickedName = inc.ReadString(); - var kickedClient = connectedClients.Find(cl => cl != c && cl.name == kickedName); + var kickedClient = connectedClients.Find(cl => cl != sender && cl.name == kickedName); if (kickedClient != null) { - Log("Client \"" + c.name + "\" kicked \"" + kickedClient.name + "\".", ServerLog.MessageType.ServerMessage); - KickClient(kickedClient, false, false); + Log("Client \"" + sender.name + "\" kicked \"" + kickedClient.name + "\".", ServerLog.MessageType.ServerMessage); + KickClient(kickedClient, "Kicked by " + sender.name, false, false); } break; case ClientPermissions.Ban: string bannedName = inc.ReadString(); - var bannedClient = connectedClients.Find(cl => cl != c && cl.name == bannedName); + var bannedClient = connectedClients.Find(cl => cl != sender && cl.name == bannedName); if (bannedClient != null) { - Log("Client \"" + c.name + "\" banned \"" + bannedClient.name + "\".", ServerLog.MessageType.ServerMessage); - KickClient(bannedClient, true, false); + Log("Client \"" + sender.name + "\" banned \"" + bannedClient.name + "\".", ServerLog.MessageType.ServerMessage); + KickClient(bannedClient, "Banned by " + sender.name, true, false); } break; case ClientPermissions.EndRound: if (gameStarted) { - Log("Client \"" + c.name + "\" ended the round.", ServerLog.MessageType.ServerMessage); + Log("Client \"" + sender.name + "\" ended the round.", ServerLog.MessageType.ServerMessage); EndGame(); } break; @@ -1416,7 +1416,7 @@ namespace Barotrauma.Networking yield return CoroutineStatus.Success; } - public override void KickPlayer(string playerName, bool ban, bool range=false) + public override void KickPlayer(string playerName, string reason, bool ban, bool range = false) { playerName = playerName.ToLowerInvariant(); @@ -1424,17 +1424,10 @@ namespace Barotrauma.Networking c.name.ToLowerInvariant() == playerName || (c.Character != null && c.Character.Name.ToLowerInvariant() == playerName)); - KickClient(client, ban, range); + KickClient(client, reason, ban, range); } - - public void KickPlayer(int id,bool ban,bool range=false) - { - Client client = connectedClients.Find(c => c.ID == id); - - KickClient(client, ban, range); - } - - public void KickClient(NetConnection conn, bool ban = false, bool range = false) + + public void KickClient(NetConnection conn, string reason, bool ban = false, bool range = false) { Client client = connectedClients.Find(c => c.Connection == conn); if (client == null) @@ -1444,30 +1437,34 @@ namespace Barotrauma.Networking { if (!banList.IsBanned(conn.RemoteEndPoint.Address.ToString())) { - banList.BanPlayer("Unnamed", conn.RemoteEndPoint.Address.ToString()); + banList.BanPlayer("Unnamed", conn.RemoteEndPoint.Address.ToString(), reason); } } } else { - KickClient(client, ban, range); + KickClient(client, reason, ban, range); } } - public void KickClient(Client client, bool ban = false, bool range = false) + public void KickClient(Client client, string reason, bool ban = false, bool range = false) { if (client == null) return; if (ban) { - DisconnectClient(client, client.name + " has been banned from the server", "You have been banned from the server"); + 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); + banList.BanPlayer(client.name, ip, reason); } else { - DisconnectClient(client, client.name + " has been kicked from the server", "You have been kicked from the server"); + 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); } } @@ -1781,14 +1778,14 @@ namespace Barotrauma.Networking if (server.Connections.Count == 0|| connectedClients.Count == 0) return; Client.UpdateKickVotes(connectedClients); - + var clientsToKick = connectedClients.FindAll(c => c.KickVoteCount >= connectedClients.Count * KickVoteRequiredRatio); foreach (Client c in clientsToKick) { - SendChatMessage(c.name+" has been kicked from the server.", ChatMessageType.Server, null); - KickClient(c); + SendChatMessage(c.name + " has been kicked from the server.", ChatMessageType.Server, null); + KickClient(c, "Kicked by vote"); } - + GameMain.NetLobbyScreen.LastUpdateID++; NetOutgoingMessage msg = server.CreateMessage(); diff --git a/Barotrauma/BarotraumaShared/Source/Networking/GameServerLogin.cs b/Barotrauma/BarotraumaShared/Source/Networking/GameServerLogin.cs index 454759900..fc31f0e02 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()); + banList.BanPlayer("Unnamed", unauthClient.Connection.RemoteEndPoint.Address.ToString(), "Too many failed login attempts."); 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 09e48d9cc..6d6344049 100644 --- a/Barotrauma/BarotraumaShared/Source/Networking/NetworkMember.cs +++ b/Barotrauma/BarotraumaShared/Source/Networking/NetworkMember.cs @@ -191,7 +191,7 @@ namespace Barotrauma.Networking #endif } - public virtual void KickPlayer(string kickedName, bool ban, bool range = false) { } + public virtual void KickPlayer(string kickedName, string reason, bool ban, bool range = false) { } public virtual void Update(float deltaTime) {