diff --git a/Barotrauma/BarotraumaClient/Source/DebugConsole.cs b/Barotrauma/BarotraumaClient/Source/DebugConsole.cs index 0283ec3d6..626969eb5 100644 --- a/Barotrauma/BarotraumaClient/Source/DebugConsole.cs +++ b/Barotrauma/BarotraumaClient/Source/DebugConsole.cs @@ -134,7 +134,7 @@ namespace Barotrauma case "entitylist": return true; default: - return false; + return client.HasConsoleCommandPermission(command); } } diff --git a/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs b/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs index aafe2d4ac..0acf9b10e 100644 --- a/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs +++ b/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs @@ -19,6 +19,7 @@ namespace Barotrauma.Networking private GUITickBox endVoteTickBox; private ClientPermissions permissions = ClientPermissions.None; + private List permittedConsoleCommands = new List(); private bool connected; @@ -596,14 +597,24 @@ namespace Barotrauma.Networking private void ReadPermissions(NetIncomingMessage inc) { + List permittedConsoleCommands = new List(); ClientPermissions newPermissions = (ClientPermissions)inc.ReadByte(); + if (newPermissions.HasFlag(ClientPermissions.ConsoleCommands)) + { + UInt16 consoleCommandCount = inc.ReadUInt16(); + for (int i = 0; i < consoleCommandCount; i++) + { + permittedConsoleCommands.Add(inc.ReadString()); + } + } + if (newPermissions != permissions) { - SetPermissions(newPermissions); + SetPermissions(newPermissions, permittedConsoleCommands); } } - private void SetPermissions(ClientPermissions newPermissions) + private void SetPermissions(ClientPermissions newPermissions, List permittedConsoleCommands) { if (newPermissions == permissions) return; GUIMessageBox.MessageBoxes.RemoveAll(mb => mb.UserData as string == "permissions"); @@ -623,6 +634,8 @@ namespace Barotrauma.Networking DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false); msg += " - " + attributes[0].Description + "\n"; } + + //TODO: display permitted console commands } permissions = newPermissions; new GUIMessageBox("Permissions changed", msg).UserData = "permissions"; @@ -800,7 +813,7 @@ namespace Barotrauma.Networking gameStarted = inc.ReadBoolean(); bool allowSpectating = inc.ReadBoolean(); - SetPermissions((ClientPermissions)inc.ReadByte()); + ReadPermissions(inc); if (gameStarted) { @@ -1161,6 +1174,14 @@ namespace Barotrauma.Networking return permissions.HasFlag(permission); } + public bool HasConsoleCommandPermission(string command) + { + if (!permissions.HasFlag(ClientPermissions.ConsoleCommands)) return false; + + command = command.ToLowerInvariant(); + return permittedConsoleCommands.Any(c => c.ToLowerInvariant() == command); + } + public override void Draw(Microsoft.Xna.Framework.Graphics.SpriteBatch spriteBatch) { base.Draw(spriteBatch); @@ -1351,6 +1372,22 @@ namespace Barotrauma.Networking client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered); } + public void SendConsoleCommand(string command) + { + if (string.IsNullOrWhiteSpace(command)) + { + DebugConsole.ThrowError("Cannot send an empty console command to the server!\n" + Environment.StackTrace); + return; + } + + NetOutgoingMessage msg = client.CreateMessage(); + msg.Write((byte)ClientPacketHeader.SERVER_COMMAND); + msg.Write((byte)ClientPermissions.ConsoleCommands); + msg.Write(command); + + client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered); + } + /// /// Tell the server to select a submarine (permission required) /// diff --git a/Barotrauma/BarotraumaShared/Source/DebugConsole.cs b/Barotrauma/BarotraumaShared/Source/DebugConsole.cs index 7c237cb9d..6c9f0105c 100644 --- a/Barotrauma/BarotraumaShared/Source/DebugConsole.cs +++ b/Barotrauma/BarotraumaShared/Source/DebugConsole.cs @@ -27,12 +27,14 @@ namespace Barotrauma static partial class DebugConsole { - class Command + public class Command { public readonly string[] names; public readonly string help; private Action onExecute; + private bool relayToServer; + public Command(string name, string help, Action onExecute) { names = name.Split('|'); @@ -40,7 +42,7 @@ namespace Barotrauma this.onExecute = onExecute; } - + public void Execute(string[] args) { onExecute(args); @@ -967,10 +969,19 @@ namespace Barotrauma } #if !DEBUG && CLIENT - if (GameMain.Client != null && !IsCommandPermitted(splitCommand[0].ToLowerInvariant(), GameMain.Client)) + if (GameMain.Client != null) { - ThrowError("You're not permitted to use the command \"" + splitCommand[0].ToLowerInvariant() + "\"!"); - return; + if (GameMain.Client.HasConsoleCommandPermission(splitCommand[0].ToLowerInvariant())) + { + GameMain.Client.SendConsoleCommand(command); + NewMessage("Server command: "+command, Color.White); + return; + } + if (!IsCommandPermitted(splitCommand[0].ToLowerInvariant(), GameMain.Client)) + { + ThrowError("You're not permitted to use the command \"" + splitCommand[0].ToLowerInvariant() + "\"!"); + return; + } } #endif @@ -987,7 +998,7 @@ namespace Barotrauma if (!commandFound) { - ThrowError("Command \""+splitCommand[0]+"\" not found."); + ThrowError("Command \"" + splitCommand[0] + "\" not found."); } } diff --git a/Barotrauma/BarotraumaShared/Source/Networking/Client.cs b/Barotrauma/BarotraumaShared/Source/Networking/Client.cs index 5a0caf60e..9497ddd10 100644 --- a/Barotrauma/BarotraumaShared/Source/Networking/Client.cs +++ b/Barotrauma/BarotraumaShared/Source/Networking/Client.cs @@ -21,7 +21,9 @@ namespace Barotrauma.Networking [Description("Select game mode")] SelectMode = 16, [Description("Manage campaign")] - ManageCampaign = 32 + ManageCampaign = 32, + [Description("Console commands")] + ConsoleCommands = 64 } class Client @@ -79,6 +81,7 @@ namespace Barotrauma.Networking public float DeleteDisconnectedTimer; public ClientPermissions Permissions = ClientPermissions.None; + public List PermittedConsoleCommands = new List(); public bool SpectateOnly; diff --git a/Barotrauma/BarotraumaShared/Source/Networking/GameServer.cs b/Barotrauma/BarotraumaShared/Source/Networking/GameServer.cs index e62b9a155..5248ddf13 100644 --- a/Barotrauma/BarotraumaShared/Source/Networking/GameServer.cs +++ b/Barotrauma/BarotraumaShared/Source/Networking/GameServer.cs @@ -1928,6 +1928,18 @@ namespace Barotrauma.Networking var msg = server.CreateMessage(); msg.Write((byte)ServerPacketHeader.PERMISSIONS); msg.Write((byte)client.Permissions); + if (client.Permissions.HasFlag(ClientPermissions.ConsoleCommands)) + { + msg.Write((UInt16)client.PermittedConsoleCommands.Sum(c => c.names.Length)); + foreach (DebugConsole.Command command in client.PermittedConsoleCommands) + { + foreach (string commandName in command.names) + { + msg.Write(commandName); + } + } + } + server.SendMessage(msg, client.Connection, NetDeliveryMethod.ReliableUnordered); SaveClientPermissions(); diff --git a/Barotrauma/BarotraumaShared/Source/Networking/GameServerSettings.cs b/Barotrauma/BarotraumaShared/Source/Networking/GameServerSettings.cs index 9034eb514..44558c72c 100644 --- a/Barotrauma/BarotraumaShared/Source/Networking/GameServerSettings.cs +++ b/Barotrauma/BarotraumaShared/Source/Networking/GameServerSettings.cs @@ -316,6 +316,8 @@ namespace Barotrauma.Networking public void LoadClientPermissions() { + //TODO: load console command permissions + if (!File.Exists(ClientPermissionsFile)) return; string[] lines; @@ -348,13 +350,15 @@ namespace Barotrauma.Networking public void SaveClientPermissions() { - GameServer.Log("Saving client permissions", ServerLog.MessageType.ServerMessage); + //TODO: save console command permissions + + Log("Saving client permissions", ServerLog.MessageType.ServerMessage); List lines = new List(); foreach (SavedClientPermission clientPermission in clientPermissions) { - lines.Add(clientPermission.Name + "|" + clientPermission.IP+"|"+clientPermission.Permissions.ToString()); + lines.Add(clientPermission.Name + "|" + clientPermission.IP + "|" + clientPermission.Permissions.ToString()); } try