mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-09-03 18:47:10 +02:00
Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
218 lines
7.5 KiB
C#
218 lines
7.5 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using Robust.Server.Player;
|
|
using Robust.Shared.Console;
|
|
using Robust.Shared.Exceptions;
|
|
using Robust.Shared.IoC;
|
|
using Robust.Shared.Network;
|
|
using Robust.Shared.Network.Messages;
|
|
using Robust.Shared.Players;
|
|
using Robust.Shared.Utility;
|
|
|
|
namespace Robust.Server.Console
|
|
{
|
|
/// <inheritdoc cref="IServerConsoleHost" />
|
|
internal sealed class ServerConsoleHost : ConsoleHost, IServerConsoleHost
|
|
{
|
|
[Dependency] private readonly IConGroupController _groupController = default!;
|
|
[Dependency] private readonly IPlayerManager _players = default!;
|
|
[Dependency] private readonly ISystemConsoleManager _systemConsole = default!;
|
|
|
|
public override event ConAnyCommandCallback? AnyCommandExecuted;
|
|
|
|
/// <inheritdoc />
|
|
public override void ExecuteCommand(ICommonSession? session, string command)
|
|
{
|
|
var shell = new ConsoleShell(this, session);
|
|
ExecuteInShell(shell, command);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public override void RemoteExecuteCommand(ICommonSession? session, string command)
|
|
{
|
|
if (!NetManager.IsConnected || session is null)
|
|
return;
|
|
|
|
var msg = NetManager.CreateNetMessage<MsgConCmd>();
|
|
msg.Text = command;
|
|
NetManager.ServerSendMessage(msg, ((IPlayerSession)session).ConnectedClient);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public override void WriteLine(ICommonSession? session, string text)
|
|
{
|
|
if (session is IPlayerSession playerSession)
|
|
OutputText(playerSession, text, false);
|
|
else
|
|
OutputText(null, text, false);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public override void WriteError(ICommonSession? session, string text)
|
|
{
|
|
if (session is IPlayerSession playerSession)
|
|
OutputText(playerSession, text, true);
|
|
else
|
|
OutputText(null, text, true);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public void Initialize()
|
|
{
|
|
RegisterCommand("sudo", "sudo make me a sandwich", "sudo <command>",(shell, argStr, _) =>
|
|
{
|
|
var localShell = shell.ConsoleHost.LocalShell;
|
|
var sudoShell = new SudoShell(this, localShell, shell);
|
|
ExecuteInShell(sudoShell, argStr.Substring("sudo ".Length));
|
|
});
|
|
|
|
LoadConsoleCommands();
|
|
|
|
// setup networking with clients
|
|
NetManager.RegisterNetMessage<MsgConCmd>(ProcessCommand);
|
|
NetManager.RegisterNetMessage<MsgConCmdAck>();
|
|
|
|
NetManager.RegisterNetMessage<MsgConCmdReg>(message => HandleRegistrationRequest(message.MsgChannel));
|
|
}
|
|
|
|
private void ExecuteInShell(IConsoleShell shell, string command)
|
|
{
|
|
try
|
|
{
|
|
var args = new List<string>();
|
|
CommandParsing.ParseArguments(command, args);
|
|
|
|
// missing cmdName
|
|
if (args.Count == 0)
|
|
return;
|
|
|
|
string? cmdName = args[0];
|
|
|
|
if (AvailableCommands.TryGetValue(cmdName, out var conCmd)) // command registered
|
|
{
|
|
args.RemoveAt(0);
|
|
var cmdArgs = args.ToArray();
|
|
if (shell.Player != null) // remote client
|
|
{
|
|
if (_groupController.CanCommand((IPlayerSession) shell.Player, cmdName)) // client has permission
|
|
{
|
|
AnyCommandExecuted?.Invoke(shell, cmdName, command, cmdArgs);
|
|
conCmd.Execute(shell, command, cmdArgs);
|
|
}
|
|
else
|
|
shell.WriteError($"Unknown command: '{cmdName}'");
|
|
}
|
|
else // system console
|
|
{
|
|
AnyCommandExecuted?.Invoke(shell, cmdName, command, cmdArgs);
|
|
conCmd.Execute(shell, command, cmdArgs);
|
|
}
|
|
}
|
|
else
|
|
shell.WriteError($"Unknown command: '{cmdName}'");
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
LogManager.GetSawmill(SawmillName).Error($"{FormatPlayerString(shell.Player)}: ExecuteError - {command}:\n{e}");
|
|
shell.WriteError($"There was an error while executing the command: {e}");
|
|
}
|
|
}
|
|
|
|
private void HandleRegistrationRequest(INetChannel senderConnection)
|
|
{
|
|
var netMgr = IoCManager.Resolve<IServerNetManager>();
|
|
var message = netMgr.CreateNetMessage<MsgConCmdReg>();
|
|
|
|
var counter = 0;
|
|
message.Commands = new MsgConCmdReg.Command[RegisteredCommands.Count];
|
|
|
|
foreach (var command in RegisteredCommands.Values)
|
|
{
|
|
message.Commands[counter++] = new MsgConCmdReg.Command
|
|
{
|
|
Name = command.Command,
|
|
Description = command.Description,
|
|
Help = command.Help
|
|
};
|
|
}
|
|
|
|
netMgr.ServerSendMessage(message, senderConnection);
|
|
}
|
|
|
|
private void ProcessCommand(MsgConCmd message)
|
|
{
|
|
string? text = message.Text;
|
|
var sender = message.MsgChannel;
|
|
var session = _players.GetSessionByChannel(sender);
|
|
|
|
LogManager.GetSawmill(SawmillName).Info($"{FormatPlayerString(session)}:{text}");
|
|
|
|
ExecuteCommand(session, text);
|
|
}
|
|
|
|
private void OutputText(IPlayerSession? session, string text, bool error)
|
|
{
|
|
if (session != null)
|
|
{
|
|
var replyMsg = NetManager.CreateNetMessage<MsgConCmdAck>();
|
|
replyMsg.Error = error;
|
|
replyMsg.Text = text;
|
|
NetManager.ServerSendMessage(replyMsg, session.ConnectedClient);
|
|
}
|
|
else
|
|
_systemConsole.Print(text + "\n");
|
|
}
|
|
|
|
private static string FormatPlayerString(ICommonSession? session)
|
|
{
|
|
return session != null ? $"{session.Name}" : "[HOST]";
|
|
}
|
|
|
|
private sealed class SudoShell : IConsoleShell
|
|
{
|
|
private readonly ServerConsoleHost _host;
|
|
private readonly IConsoleShell _owner;
|
|
private readonly IConsoleShell _sudoer;
|
|
|
|
public SudoShell(ServerConsoleHost host, IConsoleShell owner, IConsoleShell sudoer)
|
|
{
|
|
_host = host;
|
|
_owner = owner;
|
|
_sudoer = sudoer;
|
|
}
|
|
|
|
public IConsoleHost ConsoleHost => _host;
|
|
public bool IsServer => _owner.IsServer;
|
|
public ICommonSession? Player => _owner.Player;
|
|
|
|
public void ExecuteCommand(string command)
|
|
{
|
|
_host.ExecuteInShell(this, command);
|
|
}
|
|
|
|
public void RemoteExecuteCommand(string command)
|
|
{
|
|
_owner.RemoteExecuteCommand(command);
|
|
}
|
|
|
|
public void WriteLine(string text)
|
|
{
|
|
_owner.WriteLine(text);
|
|
_sudoer.WriteLine(text);
|
|
}
|
|
|
|
public void WriteError(string text)
|
|
{
|
|
_owner.WriteError(text);
|
|
_sudoer.WriteError(text);
|
|
}
|
|
|
|
public void Clear()
|
|
{
|
|
_owner.Clear();
|
|
_sudoer.Clear();
|
|
}
|
|
}
|
|
}
|
|
}
|