mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-15 20:20:46 +01:00
Compare commits
43 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
18fcab6f71 | ||
|
|
1ae6c32c62 | ||
|
|
cf6925f19b | ||
|
|
b4c7ffe38a | ||
|
|
d5c2f45f14 | ||
|
|
dcc88d2d36 | ||
|
|
a274b8dfc2 | ||
|
|
f42c1379e0 | ||
|
|
c4fa7e98d4 | ||
|
|
8b9dadffb1 | ||
|
|
5e99c6d04d | ||
|
|
606d232dbb | ||
|
|
df877582a6 | ||
|
|
8ffdb090e6 | ||
|
|
033d6ffb22 | ||
|
|
3eb6e067f9 | ||
|
|
1f64f93ef4 | ||
|
|
7dd617b0d6 | ||
|
|
0567b70704 | ||
|
|
9963e89c14 | ||
|
|
29e0faed88 | ||
|
|
0ce6ff9870 | ||
|
|
dbe9a96dfa | ||
|
|
fc5e3ab69d | ||
|
|
ed4974141c | ||
|
|
3e5efd5ed0 | ||
|
|
e1110eadb4 | ||
|
|
06ace83a73 | ||
|
|
cd01ca924b | ||
|
|
38ad8ce132 | ||
|
|
ee440c2df9 | ||
|
|
32f3c863fb | ||
|
|
b00e0bef5a | ||
|
|
0a09b27918 | ||
|
|
c9f6a4e32a | ||
|
|
b205a14f69 | ||
|
|
d5f3292e0a | ||
|
|
561e4b330e | ||
|
|
36a5d102ff | ||
|
|
b9c39e0953 | ||
|
|
ad4c8be132 | ||
|
|
988cbf9a87 | ||
|
|
e26512001a |
@@ -153,7 +153,7 @@ namespace {nameSpace}
|
||||
DiagnosticSeverity.Error,
|
||||
true),
|
||||
typeSymbol.Locations[0]));
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
|
||||
var txt = relevantXamlFile.GetText()?.ToString();
|
||||
@@ -169,7 +169,7 @@ namespace {nameSpace}
|
||||
DiagnosticSeverity.Error,
|
||||
true),
|
||||
Location.Create(xamlFileName, new TextSpan(0,0), new LinePositionSpan(new LinePosition(0,0),new LinePosition(0,0)))));
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
@@ -189,7 +189,7 @@ namespace {nameSpace}
|
||||
DiagnosticSeverity.Error,
|
||||
true),
|
||||
typeSymbol.Locations[0]));
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,9 +72,9 @@ namespace Robust.Client.Audio.Midi
|
||||
int PlayerTotalTick { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current tick of the MIDI player.
|
||||
/// Gets or sets (seeks) the current tick of the MIDI player.
|
||||
/// </summary>
|
||||
int PlayerTick { get; }
|
||||
int PlayerTick { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current tick of the sequencer.
|
||||
@@ -235,7 +235,16 @@ namespace Robust.Client.Audio.Midi
|
||||
public bool DisableProgramChangeEvent { get; set; } = true;
|
||||
|
||||
public int PlayerTotalTick => _player?.GetTotalTicks ?? 0;
|
||||
public int PlayerTick => _player?.CurrentTick ?? 0;
|
||||
public int PlayerTick
|
||||
{
|
||||
get => _player?.CurrentTick ?? 0;
|
||||
set
|
||||
{
|
||||
lock (_playerStateLock)
|
||||
_player?.Seek(Math.Max(Math.Min(value, PlayerTotalTick), 0));
|
||||
}
|
||||
}
|
||||
|
||||
public uint SequencerTick => _sequencer?.Tick ?? 0;
|
||||
public double SequencerTimeScale => _sequencer?.TimeScale ?? 0;
|
||||
|
||||
@@ -310,9 +319,8 @@ namespace Robust.Client.Audio.Midi
|
||||
|
||||
lock (_playerStateLock)
|
||||
{
|
||||
if (_player == null)
|
||||
_player = new NFluidsynth.Player(_synth);
|
||||
_player.Stop();
|
||||
_player?.Dispose();
|
||||
_player = new NFluidsynth.Player(_synth);
|
||||
_player.AddMem(buffer);
|
||||
_player.SetPlaybackCallback(MidiPlayerEventHandler);
|
||||
_player.Play();
|
||||
@@ -351,10 +359,7 @@ namespace Robust.Client.Audio.Midi
|
||||
|
||||
public void StopAllNotes()
|
||||
{
|
||||
for (var i = 0; i < 16; i++)
|
||||
{
|
||||
_synth.AllNotesOff(i);
|
||||
}
|
||||
_synth.AllNotesOff(-1);
|
||||
}
|
||||
|
||||
public void LoadSoundfont(string filename, bool resetPresets = false)
|
||||
@@ -475,12 +480,6 @@ namespace Robust.Client.Audio.Midi
|
||||
lock(_playerStateLock)
|
||||
switch (midiEvent.Type)
|
||||
{
|
||||
// Sometimes MIDI files spam these for no good reason and I can't find any info on what they are.
|
||||
case 1:
|
||||
case 5:
|
||||
case 81:
|
||||
break;
|
||||
|
||||
// Note On 0x80
|
||||
case 144:
|
||||
_synth.NoteOn(midiEvent.Channel, midiEvent.Key, midiEvent.Velocity);
|
||||
@@ -503,8 +502,10 @@ namespace Robust.Client.Audio.Midi
|
||||
|
||||
// Program Change - 0xC0
|
||||
case 192:
|
||||
if(!DisableProgramChangeEvent)
|
||||
if (!DisableProgramChangeEvent)
|
||||
_synth.ProgramChange(midiEvent.Channel, midiEvent.Program);
|
||||
else
|
||||
return;
|
||||
break;
|
||||
|
||||
// Channel Pressure - 0xD0
|
||||
@@ -517,13 +518,17 @@ namespace Robust.Client.Audio.Midi
|
||||
_synth.PitchBend(midiEvent.Channel, midiEvent.Pitch);
|
||||
break;
|
||||
|
||||
// Sometimes MIDI files spam these for no good reason and I can't find any info on what they are.
|
||||
case 1:
|
||||
case 5:
|
||||
case 81:
|
||||
// System Messages - 0xF0
|
||||
case 240:
|
||||
break;
|
||||
return;
|
||||
|
||||
default:
|
||||
_midiSawmill.Warning("Unhandled midi event of type {0}", midiEvent.Type, midiEvent);
|
||||
break;
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (FluidSynthInteropException)
|
||||
|
||||
@@ -15,7 +15,6 @@ using Robust.Shared.Interfaces.Timing;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Network.Messages;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Robust.Client
|
||||
@@ -50,12 +49,11 @@ namespace Robust.Client
|
||||
/// <inheritdoc />
|
||||
public void Initialize()
|
||||
{
|
||||
_net.RegisterNetMessage<MsgSetTickRate>(MsgSetTickRate.NAME, HandleSetTickRate);
|
||||
_net.Connected += OnConnected;
|
||||
_net.ConnectFailed += OnConnectFailed;
|
||||
_net.Disconnect += OnNetDisconnect;
|
||||
|
||||
_configManager.OnValueChanged(CVars.NetTickrate, TickRateChanged);
|
||||
_configManager.OnValueChanged(CVars.NetTickrate, TickRateChanged, invokeImmediately: true);
|
||||
|
||||
_playMan.Initialize();
|
||||
_debugDrawMan.Initialize();
|
||||
@@ -70,7 +68,7 @@ namespace Robust.Client
|
||||
}
|
||||
|
||||
_timing.TickRate = (byte) tickrate;
|
||||
Logger.InfoS("client", $"Tickrate changed to: {tickrate}");
|
||||
Logger.InfoS("client", $"Tickrate changed to: {tickrate} on tick {_timing.CurTick}");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -176,6 +174,7 @@ namespace Robust.Client
|
||||
|
||||
private void Reset()
|
||||
{
|
||||
_configManager.ClearReceivedInitialNwVars();
|
||||
OnRunLevelChanged(ClientRunLevel.Initialize);
|
||||
}
|
||||
|
||||
@@ -202,12 +201,6 @@ namespace Robust.Client
|
||||
Reset();
|
||||
}
|
||||
|
||||
private void HandleSetTickRate(MsgSetTickRate message)
|
||||
{
|
||||
_timing.TickRate = message.NewTickRate;
|
||||
Logger.InfoS("client", $"Tickrate changed to: {message.NewTickRate} on tick {_timing.CurTick}");
|
||||
}
|
||||
|
||||
private void OnLocalStatusChanged(object? obj, StatusEventArgs eventArgs)
|
||||
{
|
||||
// player finished fully connecting to the server.
|
||||
|
||||
@@ -78,7 +78,7 @@ namespace Robust.Client
|
||||
IoCManager.Register<IDebugDrawingManager, DebugDrawingManager>();
|
||||
IoCManager.Register<ILightManager, LightManager>();
|
||||
IoCManager.Register<IDiscordRichPresence, DiscordRichPresence>();
|
||||
IoCManager.Register<IClientConsole, ClientConsole>();
|
||||
IoCManager.Register<IClientConsoleHost, ClientConsoleHost>();
|
||||
IoCManager.Register<IFontManager, FontManager>();
|
||||
IoCManager.Register<IFontManagerInternal, FontManager>();
|
||||
IoCManager.Register<IMidiManager, MidiManager>();
|
||||
|
||||
@@ -1,243 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Robust.Client.Interfaces.Console;
|
||||
using Robust.Client.Log;
|
||||
using Robust.Client.Utility;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.Interfaces.Log;
|
||||
using Robust.Shared.Interfaces.Network;
|
||||
using Robust.Shared.Interfaces.Reflection;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Network.Messages;
|
||||
using Robust.Shared.Reflection;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Robust.Client.Console
|
||||
{
|
||||
public class AddStringArgs : EventArgs
|
||||
{
|
||||
public string Text { get; }
|
||||
public Color Color { get; }
|
||||
|
||||
public AddStringArgs(string text, Color color)
|
||||
{
|
||||
Text = text;
|
||||
Color = color;
|
||||
}
|
||||
}
|
||||
|
||||
public class AddFormattedMessageArgs : EventArgs
|
||||
{
|
||||
public readonly FormattedMessage Message;
|
||||
|
||||
public AddFormattedMessageArgs(FormattedMessage message)
|
||||
{
|
||||
Message = message;
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class ClientConsole : IClientConsole, IDebugConsole
|
||||
{
|
||||
private static readonly Color MsgColor = new Color(65, 105, 225);
|
||||
|
||||
[Dependency] private readonly IClientNetManager _network = default!;
|
||||
[Dependency] private readonly IReflectionManager _reflectionManager = default!;
|
||||
[Dependency] private readonly ILogManager logManager = default!;
|
||||
|
||||
private readonly Dictionary<string, IConsoleCommand> _commands = new Dictionary<string, IConsoleCommand>();
|
||||
private bool _requestedCommands;
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Initialize()
|
||||
{
|
||||
_network.RegisterNetMessage<MsgConCmdReg>(MsgConCmdReg.NAME, HandleConCmdReg);
|
||||
_network.RegisterNetMessage<MsgConCmdAck>(MsgConCmdAck.NAME, HandleConCmdAck);
|
||||
_network.RegisterNetMessage<MsgConCmd>(MsgConCmd.NAME);
|
||||
|
||||
Reset();
|
||||
logManager.RootSawmill.AddHandler(new DebugConsoleLogHandler(this));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Reset()
|
||||
{
|
||||
_commands.Clear();
|
||||
_requestedCommands = false;
|
||||
_network.Connected += OnNetworkConnected;
|
||||
|
||||
InitializeCommands();
|
||||
SendServerCommandRequest();
|
||||
}
|
||||
|
||||
private void OnNetworkConnected(object? sender, NetChannelArgs netChannelArgs)
|
||||
{
|
||||
SendServerCommandRequest();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
// We don't have anything to dispose.
|
||||
}
|
||||
|
||||
public IReadOnlyDictionary<string, IConsoleCommand> Commands => _commands;
|
||||
|
||||
public void AddLine(string text, Color color)
|
||||
{
|
||||
AddString?.Invoke(this, new AddStringArgs(text, color));
|
||||
}
|
||||
|
||||
public void AddLine(string text)
|
||||
{
|
||||
AddLine(text, Color.White);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
ClearText?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
public event EventHandler<AddStringArgs>? AddString;
|
||||
public event EventHandler? ClearText;
|
||||
public event EventHandler<AddFormattedMessageArgs>? AddFormatted;
|
||||
|
||||
private void HandleConCmdAck(MsgConCmdAck msg)
|
||||
{
|
||||
AddLine("< " + msg.Text, MsgColor);
|
||||
}
|
||||
|
||||
private void HandleConCmdReg(MsgConCmdReg msg)
|
||||
{
|
||||
foreach (var cmd in msg.Commands)
|
||||
{
|
||||
var commandName = cmd.Name;
|
||||
|
||||
// Do not do duplicate commands.
|
||||
if (_commands.ContainsKey(commandName))
|
||||
{
|
||||
Logger.DebugS("console", $"Server sent console command {commandName}, but we already have one with the same name. Ignoring.");
|
||||
continue;
|
||||
}
|
||||
|
||||
var command = new ServerDummyCommand(commandName, cmd.Help, cmd.Description);
|
||||
_commands[commandName] = command;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Processes commands (chat messages starting with /)
|
||||
/// </summary>
|
||||
/// <param name="text">input text</param>
|
||||
public void ProcessCommand(string text)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(text))
|
||||
return;
|
||||
|
||||
// echo the command locally
|
||||
AddLine("> " + text, Color.Lime);
|
||||
|
||||
//Commands are processed locally and then sent to the server to be processed there again.
|
||||
var args = new List<string>();
|
||||
|
||||
CommandParsing.ParseArguments(text, args);
|
||||
|
||||
var commandname = args[0];
|
||||
|
||||
var forward = true;
|
||||
if (_commands.ContainsKey(commandname))
|
||||
{
|
||||
var command = _commands[commandname];
|
||||
args.RemoveAt(0);
|
||||
forward = command.Execute(this, args.ToArray());
|
||||
}
|
||||
else if (!_network.IsConnected)
|
||||
{
|
||||
AddLine("Unknown command: " + commandname, Color.Red);
|
||||
return;
|
||||
}
|
||||
|
||||
if (forward)
|
||||
SendServerConsoleCommand(text);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Locates and registeres all local commands.
|
||||
/// </summary>
|
||||
private void InitializeCommands()
|
||||
{
|
||||
foreach (var t in _reflectionManager.GetAllChildren<IConsoleCommand>())
|
||||
{
|
||||
var instance = (IConsoleCommand)Activator.CreateInstance(t)!;
|
||||
if (_commands.ContainsKey(instance.Command))
|
||||
throw new InvalidOperationException($"Command already registered: {instance.Command}");
|
||||
|
||||
_commands[instance.Command] = instance;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Requests remote commands from server.
|
||||
/// </summary>
|
||||
public void SendServerCommandRequest()
|
||||
{
|
||||
if (_requestedCommands)
|
||||
return;
|
||||
|
||||
if (!_network.IsConnected)
|
||||
return;
|
||||
|
||||
var msg = _network.CreateNetMessage<MsgConCmdReg>();
|
||||
_network.ClientSendMessage(msg);
|
||||
|
||||
_requestedCommands = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a command directly to the server.
|
||||
/// </summary>
|
||||
private void SendServerConsoleCommand(string text)
|
||||
{
|
||||
if (_network == null || !_network.IsConnected)
|
||||
return;
|
||||
|
||||
var msg = _network.CreateNetMessage<MsgConCmd>();
|
||||
msg.Text = text;
|
||||
_network.ClientSendMessage(msg);
|
||||
}
|
||||
|
||||
public void AddFormattedLine(FormattedMessage message)
|
||||
{
|
||||
// Why the hell does this class implement IDebugConsole.
|
||||
AddFormatted?.Invoke(this, new AddFormattedMessageArgs(message));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// These dummies are made purely so list and help can list server-side commands.
|
||||
/// </summary>
|
||||
[Reflect(false)]
|
||||
internal class ServerDummyCommand : IConsoleCommand
|
||||
{
|
||||
internal ServerDummyCommand(string command, string help, string description)
|
||||
{
|
||||
Command = command;
|
||||
Help = help;
|
||||
Description = description;
|
||||
}
|
||||
|
||||
public string Command { get; }
|
||||
|
||||
public string Help { get; }
|
||||
|
||||
public string Description { get; }
|
||||
|
||||
// Always forward to server.
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
198
Robust.Client/Console/ClientConsoleHost.cs
Normal file
198
Robust.Client/Console/ClientConsoleHost.cs
Normal file
@@ -0,0 +1,198 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Robust.Client.Log;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Network.Messages;
|
||||
using Robust.Shared.Players;
|
||||
using Robust.Shared.Reflection;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Robust.Client.Console
|
||||
{
|
||||
public class AddStringArgs : EventArgs
|
||||
{
|
||||
public Color Color { get; }
|
||||
public string Text { get; }
|
||||
|
||||
public AddStringArgs(string text, Color color)
|
||||
{
|
||||
Text = text;
|
||||
Color = color;
|
||||
}
|
||||
}
|
||||
|
||||
public class AddFormattedMessageArgs : EventArgs
|
||||
{
|
||||
public readonly FormattedMessage Message;
|
||||
|
||||
public AddFormattedMessageArgs(FormattedMessage message)
|
||||
{
|
||||
Message = message;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IClientConsoleHost" />
|
||||
internal class ClientConsoleHost : ConsoleHost, IClientConsoleHost
|
||||
{
|
||||
private static readonly Color _msgColor = new(65, 105, 225);
|
||||
|
||||
private bool _requestedCommands;
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Initialize()
|
||||
{
|
||||
NetManager.RegisterNetMessage<MsgConCmdReg>(MsgConCmdReg.NAME, HandleConCmdReg);
|
||||
NetManager.RegisterNetMessage<MsgConCmdAck>(MsgConCmdAck.NAME, HandleConCmdAck);
|
||||
NetManager.RegisterNetMessage<MsgConCmd>(MsgConCmd.NAME);
|
||||
|
||||
Reset();
|
||||
LogManager.RootSawmill.AddHandler(new DebugConsoleLogHandler(this));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Reset()
|
||||
{
|
||||
AvailableCommands.Clear();
|
||||
_requestedCommands = false;
|
||||
NetManager.Connected += OnNetworkConnected;
|
||||
|
||||
LoadConsoleCommands();
|
||||
SendServerCommandRequest();
|
||||
}
|
||||
|
||||
public event EventHandler<AddStringArgs>? AddString;
|
||||
public event EventHandler<AddFormattedMessageArgs>? AddFormatted;
|
||||
|
||||
public void AddFormattedLine(FormattedMessage message)
|
||||
{
|
||||
AddFormatted?.Invoke(this, new AddFormattedMessageArgs(message));
|
||||
}
|
||||
|
||||
public override void WriteLine(ICommonSession? session, string text, Color color)
|
||||
{
|
||||
AddString?.Invoke(this, new AddStringArgs(text, color));
|
||||
}
|
||||
|
||||
public override void ExecuteCommand(ICommonSession? session, string command)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(command))
|
||||
return;
|
||||
|
||||
// echo the command locally
|
||||
WriteLine(null, "> " + command, Color.Lime);
|
||||
|
||||
//Commands are processed locally and then sent to the server to be processed there again.
|
||||
var args = new List<string>();
|
||||
|
||||
CommandParsing.ParseArguments(command, args);
|
||||
|
||||
var commandname = args[0];
|
||||
|
||||
if (AvailableCommands.ContainsKey(commandname))
|
||||
{
|
||||
var command1 = AvailableCommands[commandname];
|
||||
args.RemoveAt(0);
|
||||
command1.Execute(new ConsoleShell(this, null), command, args.ToArray());
|
||||
}
|
||||
else if (!NetManager.IsConnected) WriteLine(null, "Unknown command: " + commandname, Color.Red);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a command directly to the server.
|
||||
/// </summary>
|
||||
public override void RemoteExecuteCommand(ICommonSession? session, string command)
|
||||
{
|
||||
if (!NetManager.IsConnected)
|
||||
return;
|
||||
|
||||
var msg = NetManager.CreateNetMessage<MsgConCmd>();
|
||||
msg.Text = command;
|
||||
NetManager.ClientSendMessage(msg);
|
||||
}
|
||||
|
||||
public override void WriteLine(ICommonSession? session, string text)
|
||||
{
|
||||
WriteLine(null, text, Color.White);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
// We don't have anything to dispose.
|
||||
}
|
||||
|
||||
private void OnNetworkConnected(object? sender, NetChannelArgs netChannelArgs)
|
||||
{
|
||||
SendServerCommandRequest();
|
||||
}
|
||||
|
||||
private void HandleConCmdAck(MsgConCmdAck msg)
|
||||
{
|
||||
WriteLine(null, "< " + msg.Text, _msgColor);
|
||||
}
|
||||
|
||||
private void HandleConCmdReg(MsgConCmdReg msg)
|
||||
{
|
||||
foreach (var cmd in msg.Commands)
|
||||
{
|
||||
var commandName = cmd.Name;
|
||||
|
||||
// Do not do duplicate commands.
|
||||
if (AvailableCommands.ContainsKey(commandName))
|
||||
{
|
||||
Logger.DebugS("console", $"Server sent console command {commandName}, but we already have one with the same name. Ignoring.");
|
||||
continue;
|
||||
}
|
||||
|
||||
var command = new ServerDummyCommand(commandName, cmd.Help, cmd.Description);
|
||||
AvailableCommands[commandName] = command;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Requests remote commands from server.
|
||||
/// </summary>
|
||||
private void SendServerCommandRequest()
|
||||
{
|
||||
if (_requestedCommands)
|
||||
return;
|
||||
|
||||
if (!NetManager.IsConnected)
|
||||
return;
|
||||
|
||||
var msg = NetManager.CreateNetMessage<MsgConCmdReg>();
|
||||
NetManager.ClientSendMessage(msg);
|
||||
|
||||
_requestedCommands = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// These dummies are made purely so list and help can list server-side commands.
|
||||
/// </summary>
|
||||
[Reflect(false)]
|
||||
internal class ServerDummyCommand : IConsoleCommand
|
||||
{
|
||||
public string Command { get; }
|
||||
|
||||
public string Description { get; }
|
||||
|
||||
public string Help { get; }
|
||||
|
||||
internal ServerDummyCommand(string command, string help, string description)
|
||||
{
|
||||
Command = command;
|
||||
Help = help;
|
||||
Description = description;
|
||||
}
|
||||
|
||||
// Always forward to server.
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
shell.RemoteExecuteCommand(argStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.Interfaces.Console;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
@@ -14,13 +14,13 @@ namespace Robust.Client.Console.Commands
|
||||
public string Description => "Adds a component to an entity on the client";
|
||||
public string Help => "addcompc <uid> <componentName>";
|
||||
|
||||
public bool Execute(IDebugConsole shell, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
|
||||
if (args.Length != 2)
|
||||
{
|
||||
shell.AddLine("Wrong number of arguments");
|
||||
return false;
|
||||
shell.WriteLine("Wrong number of arguments");
|
||||
return;
|
||||
}
|
||||
|
||||
var entityUid = EntityUid.Parse(args[0]);
|
||||
@@ -36,8 +36,6 @@ namespace Robust.Client.Console.Commands
|
||||
component.Owner = entity;
|
||||
|
||||
compManager.AddComponent(entity, component);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,12 +46,12 @@ namespace Robust.Client.Console.Commands
|
||||
public string Description => "Removes a component from an entity.";
|
||||
public string Help => "rmcompc <uid> <componentName>";
|
||||
|
||||
public bool Execute(IDebugConsole shell, string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (args.Length != 2)
|
||||
{
|
||||
shell.AddLine("Wrong number of arguments");
|
||||
return false;
|
||||
shell.WriteLine("Wrong number of arguments");
|
||||
return;
|
||||
}
|
||||
|
||||
var entityUid = EntityUid.Parse(args[0]);
|
||||
@@ -65,8 +63,6 @@ namespace Robust.Client.Console.Commands
|
||||
var registration = compFactory.GetRegistration(componentName);
|
||||
|
||||
compManager.RemoveComponent(entityUid, registration.Type);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.Interfaces.Console;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
|
||||
@@ -13,18 +13,17 @@ namespace Robust.Client.Console.Commands
|
||||
public string Description => "Spawns a client-side entity with specific type at your feet.";
|
||||
public string Help => "cspawn <entity type>";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var player = IoCManager.Resolve<IPlayerManager>().LocalPlayer;
|
||||
if (player?.ControlledEntity == null)
|
||||
{
|
||||
console.AddLine("You don't have an attached entity.");
|
||||
return false;
|
||||
shell.WriteLine("You don't have an attached entity.");
|
||||
return;
|
||||
}
|
||||
|
||||
var entityManager = IoCManager.Resolve<IEntityManager>();
|
||||
entityManager.SpawnEntity(args[0], player.ControlledEntity.Transform.Coordinates);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.Interfaces.Console;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.Interfaces.Configuration;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Maths;
|
||||
@@ -12,12 +12,12 @@ namespace Robust.Client.Console.Commands
|
||||
[UsedImplicitly]
|
||||
internal sealed class CVarCommand : SharedCVarCommand, IConsoleCommand
|
||||
{
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public override void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (args.Length < 1 || args.Length > 2)
|
||||
{
|
||||
console.AddLine("Must provide exactly one or two arguments.", Color.Red);
|
||||
return false;
|
||||
shell.WriteLine("Must provide exactly one or two arguments.", Color.Red);
|
||||
return;
|
||||
}
|
||||
|
||||
var configManager = IoCManager.Resolve<IConfigurationManager>();
|
||||
@@ -26,21 +26,21 @@ namespace Robust.Client.Console.Commands
|
||||
if (name == "?")
|
||||
{
|
||||
var cvars = configManager.GetRegisteredCVars().OrderBy(c => c);
|
||||
console.AddLine(string.Join("\n", cvars));
|
||||
return false;
|
||||
shell.WriteLine(string.Join("\n", cvars));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!configManager.IsCVarRegistered(name))
|
||||
{
|
||||
console.AddLine($"CVar '{name}' is not registered. Use 'cvar ?' to get a list of all registered CVars.", Color.Red);
|
||||
return false;
|
||||
shell.WriteLine($"CVar '{name}' is not registered. Use 'cvar ?' to get a list of all registered CVars.", Color.Red);
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.Length == 1)
|
||||
{
|
||||
// Read CVar
|
||||
var value = configManager.GetCVar<object>(name);
|
||||
console.AddLine(value.ToString() ?? "");
|
||||
shell.WriteLine(value.ToString() ?? "");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -54,11 +54,9 @@ namespace Robust.Client.Console.Commands
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
console.AddLine($"Input value is in incorrect format for type {type}");
|
||||
shell.WriteLine($"Input value is in incorrect format for type {type}");
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,10 +67,9 @@ namespace Robust.Client.Console.Commands
|
||||
public string Description => "Saves the client configuration to the config file";
|
||||
public string Help => "saveconfig";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
IoCManager.Resolve<IConfigurationManager>().SaveToFile();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
// This file is for commands that do something to the console itself.
|
||||
// This file is for commands that do something to the console itself.
|
||||
// Not some generic console command type.
|
||||
// Couldn't think of a better name sorry.
|
||||
|
||||
using System;
|
||||
using Robust.Client.Interfaces.Console;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.Interfaces.Random;
|
||||
using Robust.Shared.IoC;
|
||||
@@ -17,10 +16,9 @@ namespace Robust.Client.Console.Commands
|
||||
public string Help => "Clears the debug console of all messages.";
|
||||
public string Description => "Clears the console.";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
console.Clear();
|
||||
return false;
|
||||
shell.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,15 +28,14 @@ namespace Robust.Client.Console.Commands
|
||||
public string Help => "Fills the console with some nonsense for debugging.";
|
||||
public string Description => "Fill up the console for debugging.";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
Color[] colors = { Color.Green, Color.Blue, Color.Red };
|
||||
var random = IoCManager.Resolve<IRobustRandom>();
|
||||
for (int x = 0; x < 50; x++)
|
||||
{
|
||||
console.AddLine("filling...", colors[random.Next(0, colors.Length)]);
|
||||
shell.WriteLine("filling...", colors[random.Next(0, colors.Length)]);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ using System.Text.RegularExpressions;
|
||||
using Robust.Client.Input;
|
||||
using System.Threading;
|
||||
using Robust.Client.Interfaces;
|
||||
using Robust.Client.Interfaces.Console;
|
||||
using Robust.Client.Interfaces.Debugging;
|
||||
using Robust.Client.Interfaces.Graphics;
|
||||
using Robust.Client.Interfaces.Graphics.ClientEye;
|
||||
@@ -26,6 +25,7 @@ using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Shared.Asynchronous;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.ContentPack;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameObjects.Components.Transform;
|
||||
@@ -49,16 +49,14 @@ namespace Robust.Client.Console.Commands
|
||||
public string Help => "Dump entity list";
|
||||
public string Description => "Dumps entity list of UIDs and prototype.";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var entityManager = IoCManager.Resolve<IEntityManager>();
|
||||
|
||||
foreach (var e in entityManager.GetEntities().OrderBy(e => e.Uid))
|
||||
{
|
||||
console.AddLine($"entity {e.Uid}, {e.Prototype?.ID}, {e.Transform.Coordinates}.", Color.White);
|
||||
shell.WriteLine($"entity {e.Uid}, {e.Prototype?.ID}, {e.Transform.Coordinates}.", Color.White);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,12 +66,12 @@ namespace Robust.Client.Console.Commands
|
||||
public string Help => "Usage: getcomponentregistration <componentName>";
|
||||
public string Description => "Gets component registration information";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (args.Length < 1)
|
||||
{
|
||||
console.AddLine(Help);
|
||||
return false;
|
||||
shell.WriteLine(Help);
|
||||
return;
|
||||
}
|
||||
|
||||
var componentFactory = IoCManager.Resolve<IComponentFactory>();
|
||||
@@ -94,19 +92,17 @@ namespace Robust.Client.Console.Commands
|
||||
|
||||
message.Append($", NSE: {registration.NetworkSynchronizeExistence}, references:");
|
||||
|
||||
console.AddLine(message.ToString(), Color.White);
|
||||
shell.WriteLine(message.ToString(), Color.White);
|
||||
|
||||
foreach (var type in registration.References)
|
||||
{
|
||||
console.AddLine($" {type}", Color.White);
|
||||
shell.WriteLine($" {type}", Color.White);
|
||||
}
|
||||
}
|
||||
catch (UnknownComponentException)
|
||||
{
|
||||
console.AddLine($"No registration found for '{args[0]}'", Color.Red);
|
||||
shell.WriteLine($"No registration found for '{args[0]}'", Color.Red);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,14 +115,14 @@ namespace Robust.Client.Console.Commands
|
||||
|
||||
public string Description => "Toggles a debug monitor in the F3 menu.";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var monitor = IoCManager.Resolve<IUserInterfaceManager>().DebugMonitors;
|
||||
|
||||
if (args.Length != 1)
|
||||
{
|
||||
console.AddLine(Help);
|
||||
return false;
|
||||
shell.WriteLine(Help);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (args[0])
|
||||
@@ -159,11 +155,9 @@ namespace Robust.Client.Console.Commands
|
||||
monitor.ShowInput ^= true;
|
||||
break;
|
||||
default:
|
||||
console.AddLine($"Invalid key: {args[0]}");
|
||||
shell.WriteLine($"Invalid key: {args[0]}");
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,7 +167,7 @@ namespace Robust.Client.Console.Commands
|
||||
public string Help => "Throws an exception";
|
||||
public string Description => "Throws an exception";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
throw new InvalidOperationException("Fuck");
|
||||
}
|
||||
@@ -185,11 +179,10 @@ namespace Robust.Client.Console.Commands
|
||||
public string Help => "";
|
||||
public string Description => "Enables debug drawing over all bounding boxes in the game, showing their size.";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var mgr = IoCManager.Resolve<IDebugDrawing>();
|
||||
mgr.DebugColliders = !mgr.DebugColliders;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,11 +192,10 @@ namespace Robust.Client.Console.Commands
|
||||
public string Help => "";
|
||||
public string Description => "Enables debug drawing over all entity positions in the game.";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var mgr = IoCManager.Resolve<IDebugDrawing>();
|
||||
mgr.DebugPositions = !mgr.DebugPositions;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,25 +205,24 @@ namespace Robust.Client.Console.Commands
|
||||
public string Help => "Usage: showrays <raylifetime>";
|
||||
public string Description => "Toggles debug drawing of physics rays. An integer for <raylifetime> must be provided";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (args.Length != 1)
|
||||
{
|
||||
console.AddLine(Help);
|
||||
return false;
|
||||
shell.WriteLine(Help);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!int.TryParse(args[0], out var id))
|
||||
{
|
||||
console.AddLine($"{args[0]} is not a valid integer.",Color.Red);
|
||||
return false;
|
||||
shell.WriteLine($"{args[0]} is not a valid integer.",Color.Red);
|
||||
return;
|
||||
}
|
||||
|
||||
var mgr = IoCManager.Resolve<IDebugDrawingManager>();
|
||||
mgr.DebugDrawRays = !mgr.DebugDrawRays;
|
||||
console.AddLine("Toggled showing rays to:" + mgr.DebugDrawRays.ToString(), Color.Green);
|
||||
shell.WriteLine("Toggled showing rays to:" + mgr.DebugDrawRays.ToString(), Color.Green);
|
||||
mgr.DebugRayLifetime = TimeSpan.FromSeconds((double)int.Parse(args[0], CultureInfo.InvariantCulture));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -241,10 +232,9 @@ namespace Robust.Client.Console.Commands
|
||||
public string Help => "";
|
||||
public string Description => "Immediately disconnect from the server and go back to the main menu.";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
IoCManager.Resolve<IClientNetManager>().ClientDisconnect("Disconnect command used.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,33 +247,33 @@ namespace Robust.Client.Console.Commands
|
||||
|
||||
public string Description => "Displays verbose diagnostics for an entity.";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (args.Length != 1)
|
||||
{
|
||||
console.AddLine(Help);
|
||||
return false;
|
||||
shell.WriteLine(Help);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((!new Regex(@"^c?[0-9]+$").IsMatch(args[0])))
|
||||
{
|
||||
console.AddLine("Malformed UID", Color.Red);
|
||||
return false;
|
||||
shell.WriteLine("Malformed UID", Color.Red);
|
||||
return;
|
||||
}
|
||||
|
||||
var uid = EntityUid.Parse(args[0]);
|
||||
var entmgr = IoCManager.Resolve<IEntityManager>();
|
||||
if (!entmgr.TryGetEntity(uid, out var entity))
|
||||
{
|
||||
console.AddLine("That entity does not exist. Sorry lad.", Color.Red);
|
||||
return false;
|
||||
shell.WriteLine("That entity does not exist. Sorry lad.", Color.Red);
|
||||
return;
|
||||
}
|
||||
|
||||
console.AddLine($"{entity.Uid}: {entity.Prototype?.ID}/{entity.Name}");
|
||||
console.AddLine($"init/del/lmt: {entity.Initialized}/{entity.Deleted}/{entity.LastModifiedTick}");
|
||||
shell.WriteLine($"{entity.Uid}: {entity.Prototype?.ID}/{entity.Name}");
|
||||
shell.WriteLine($"init/del/lmt: {entity.Initialized}/{entity.Deleted}/{entity.LastModifiedTick}");
|
||||
foreach (var component in entity.GetAllComponents())
|
||||
{
|
||||
console.AddLine(component.ToString() ?? "");
|
||||
shell.WriteLine(component.ToString() ?? "");
|
||||
if (component is IComponentDebug debug)
|
||||
{
|
||||
foreach (var line in debug.GetDebugString().Split('\n'))
|
||||
@@ -293,12 +283,10 @@ namespace Robust.Client.Console.Commands
|
||||
continue;
|
||||
}
|
||||
|
||||
console.AddLine("\t" + line);
|
||||
shell.WriteLine("\t" + line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -308,12 +296,12 @@ namespace Robust.Client.Console.Commands
|
||||
public string Help => "sggcell <gridID> <vector2i> [offset]\nThat vector2i param is in the form x<int>,y<int>.";
|
||||
public string Description => "Lists entities on a snap grid cell.";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (args.Length != 2 && args.Length != 3)
|
||||
{
|
||||
console.AddLine(Help);
|
||||
return false;
|
||||
shell.WriteLine(Help);
|
||||
return;
|
||||
}
|
||||
|
||||
string gridId = args[0];
|
||||
@@ -322,14 +310,14 @@ namespace Robust.Client.Console.Commands
|
||||
|
||||
if (!int.TryParse(args[0], out var id))
|
||||
{
|
||||
console.AddLine($"{args[0]} is not a valid integer.",Color.Red);
|
||||
return false;
|
||||
shell.WriteLine($"{args[0]} is not a valid integer.",Color.Red);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!new Regex(@"^-?[0-9]+,-?[0-9]+$").IsMatch(indices))
|
||||
{
|
||||
console.AddLine("mapIndicies must be of form x<int>,y<int>", Color.Red);
|
||||
return false;
|
||||
shell.WriteLine("mapIndicies must be of form x<int>,y<int>", Color.Red);
|
||||
return;
|
||||
}
|
||||
|
||||
SnapGridOffset selectedOffset;
|
||||
@@ -339,8 +327,8 @@ namespace Robust.Client.Console.Commands
|
||||
}
|
||||
else
|
||||
{
|
||||
console.AddLine("given offset type is not defined", Color.Red);
|
||||
return false;
|
||||
shell.WriteLine("given offset type is not defined", Color.Red);
|
||||
return;
|
||||
}
|
||||
|
||||
var mapMan = IoCManager.Resolve<IMapManager>();
|
||||
@@ -354,16 +342,13 @@ namespace Robust.Client.Console.Commands
|
||||
int.Parse(indices.Split(',')[1], CultureInfo.InvariantCulture)),
|
||||
selectedOffset))
|
||||
{
|
||||
console.AddLine(entity.Owner.Uid.ToString());
|
||||
shell.WriteLine(entity.Owner.Uid.ToString());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
console.AddLine("grid does not exist", Color.Red);
|
||||
return false;
|
||||
shell.WriteLine("grid does not exist", Color.Red);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -373,19 +358,17 @@ namespace Robust.Client.Console.Commands
|
||||
public string Description => "Changes the name used when attempting to connect to the server.";
|
||||
public string Help => Command + " <name>";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (args.Length < 1)
|
||||
{
|
||||
console.AddLine(Help);
|
||||
return false;
|
||||
shell.WriteLine(Help);
|
||||
return;
|
||||
}
|
||||
var client = IoCManager.Resolve<IBaseClient>();
|
||||
client.PlayerNameOverride = args[0];
|
||||
|
||||
console.AddLine($"Overriding player name to \"{args[0]}\".", Color.White);
|
||||
|
||||
return false;
|
||||
shell.WriteLine($"Overriding player name to \"{args[0]}\".", Color.White);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -395,12 +378,12 @@ namespace Robust.Client.Console.Commands
|
||||
public string Description => "Pre-caches a resource.";
|
||||
public string Help => "ldrsc <path> <type>";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (args.Length < 2)
|
||||
{
|
||||
console.AddLine(Help);
|
||||
return false;
|
||||
shell.WriteLine(Help);
|
||||
return;
|
||||
}
|
||||
var resourceCache = IoCManager.Resolve<IResourceCache>();
|
||||
var reflection = IoCManager.Resolve<IReflectionManager>();
|
||||
@@ -412,8 +395,8 @@ namespace Robust.Client.Console.Commands
|
||||
}
|
||||
catch(ArgumentException)
|
||||
{
|
||||
console.AddLine("Unable to find type", Color.Red);
|
||||
return false;
|
||||
shell.WriteLine("Unable to find type", Color.Red);
|
||||
return;
|
||||
}
|
||||
|
||||
var getResourceMethod =
|
||||
@@ -423,7 +406,6 @@ namespace Robust.Client.Console.Commands
|
||||
DebugTools.Assert(getResourceMethod != null);
|
||||
var generic = getResourceMethod!.MakeGenericMethod(type);
|
||||
generic.Invoke(resourceCache, new object[] { args[0], true });
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -433,12 +415,12 @@ namespace Robust.Client.Console.Commands
|
||||
public string Description => "Reloads a resource.";
|
||||
public string Help => "rldrsc <path> <type>";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (args.Length < 2)
|
||||
{
|
||||
console.AddLine(Help);
|
||||
return false;
|
||||
shell.WriteLine(Help);
|
||||
return;
|
||||
}
|
||||
var resourceCache = IoCManager.Resolve<IResourceCache>();
|
||||
var reflection = IoCManager.Resolve<IReflectionManager>();
|
||||
@@ -450,15 +432,14 @@ namespace Robust.Client.Console.Commands
|
||||
}
|
||||
catch(ArgumentException)
|
||||
{
|
||||
console.AddLine("Unable to find type", Color.Red);
|
||||
return false;
|
||||
shell.WriteLine("Unable to find type", Color.Red);
|
||||
return;
|
||||
}
|
||||
|
||||
var getResourceMethod = resourceCache.GetType().GetMethod("ReloadResource", new[] { typeof(string) });
|
||||
DebugTools.Assert(getResourceMethod != null);
|
||||
var generic = getResourceMethod!.MakeGenericMethod(type);
|
||||
generic.Invoke(resourceCache, new object[] { args[0] });
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -468,18 +449,18 @@ namespace Robust.Client.Console.Commands
|
||||
public string Description => "Gets the tile count of a grid";
|
||||
public string Help => "Usage: gridtc <gridId>";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (args.Length != 1)
|
||||
{
|
||||
console.AddLine(Help);
|
||||
return false;
|
||||
shell.WriteLine(Help);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!int.TryParse(args[0], out var id))
|
||||
{
|
||||
console.AddLine($"{args[0]} is not a valid integer.");
|
||||
return false;
|
||||
shell.WriteLine($"{args[0]} is not a valid integer.");
|
||||
return;
|
||||
}
|
||||
|
||||
var gridId = new GridId(int.Parse(args[0]));
|
||||
@@ -487,13 +468,11 @@ namespace Robust.Client.Console.Commands
|
||||
|
||||
if (mapManager.TryGetGrid(gridId, out var grid))
|
||||
{
|
||||
console.AddLine(mapManager.GetGrid(gridId).GetAllTiles().Count().ToString());
|
||||
return false;
|
||||
shell.WriteLine(mapManager.GetGrid(gridId).GetAllTiles().Count().ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
console.AddLine($"No grid exists with id {id}",Color.Red);
|
||||
return false;
|
||||
shell.WriteLine($"No grid exists with id {id}",Color.Red);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -504,7 +483,7 @@ namespace Robust.Client.Console.Commands
|
||||
public string Description => "Dump GUI tree to /guidump.txt in user data.";
|
||||
public string Help => "guidump";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var root = IoCManager.Resolve<IUserInterfaceManager>().RootControl;
|
||||
var res = IoCManager.Resolve<IResourceManager>();
|
||||
@@ -514,8 +493,6 @@ namespace Robust.Client.Console.Commands
|
||||
{
|
||||
_writeNode(root, 0, writer);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void _writeNode(Control control, int indents, TextWriter writer)
|
||||
@@ -575,7 +552,7 @@ namespace Robust.Client.Console.Commands
|
||||
public string Description => "Open a dummy UI testing window";
|
||||
public string Help => "uitest";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var window = new SS14Window { CustomMinimumSize = (500, 400)};
|
||||
var tabContainer = new TabContainer();
|
||||
@@ -667,8 +644,6 @@ namespace Robust.Client.Console.Commands
|
||||
});
|
||||
|
||||
window.OpenCentered();
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -678,11 +653,10 @@ namespace Robust.Client.Console.Commands
|
||||
public string Description => "Sets the system clipboard";
|
||||
public string Help => "setclipboard <text>";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var mgr = IoCManager.Resolve<IClipboardManager>();
|
||||
mgr.SetText(args[0]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -692,11 +666,10 @@ namespace Robust.Client.Console.Commands
|
||||
public string Description => "Gets the system clipboard";
|
||||
public string Help => "getclipboard";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var mgr = IoCManager.Resolve<IClipboardManager>();
|
||||
console.AddLine(mgr.GetText());
|
||||
return false;
|
||||
shell.WriteLine(mgr.GetText());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -706,11 +679,11 @@ namespace Robust.Client.Console.Commands
|
||||
public string Description => "Toggles light rendering.";
|
||||
public string Help => "togglelight";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var mgr = IoCManager.Resolve<ILightManager>();
|
||||
mgr.Enabled = !mgr.Enabled;
|
||||
return false;
|
||||
if (!mgr.LockConsoleAccess)
|
||||
mgr.Enabled = !mgr.Enabled;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -720,12 +693,11 @@ namespace Robust.Client.Console.Commands
|
||||
public string Description => "Toggles fov for client.";
|
||||
public string Help => "togglefov";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var mgr = IoCManager.Resolve<IEyeManager>();
|
||||
if (mgr.CurrentEye != null)
|
||||
mgr.CurrentEye.DrawFov = !mgr.CurrentEye.DrawFov;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -735,11 +707,11 @@ namespace Robust.Client.Console.Commands
|
||||
public string Description => "Toggles hard fov for client (for debugging space-station-14#2353).";
|
||||
public string Help => "togglehardfov";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var mgr = IoCManager.Resolve<ILightManager>();
|
||||
mgr.DrawHardFov = !mgr.DrawHardFov;
|
||||
return false;
|
||||
if (!mgr.LockConsoleAccess)
|
||||
mgr.DrawHardFov = !mgr.DrawHardFov;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -749,11 +721,24 @@ namespace Robust.Client.Console.Commands
|
||||
public string Description => "Toggles shadow rendering.";
|
||||
public string Help => "toggleshadows";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var mgr = IoCManager.Resolve<ILightManager>();
|
||||
mgr.DrawShadows = !mgr.DrawShadows;
|
||||
return false;
|
||||
if (!mgr.LockConsoleAccess)
|
||||
mgr.DrawShadows = !mgr.DrawShadows;
|
||||
}
|
||||
}
|
||||
internal class ToggleLightBuf : IConsoleCommand
|
||||
{
|
||||
public string Command => "togglelightbuf";
|
||||
public string Description => "Toggles lighting rendering. This includes shadows but not FOV.";
|
||||
public string Help => "togglelightbuf";
|
||||
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var mgr = IoCManager.Resolve<ILightManager>();
|
||||
if (!mgr.LockConsoleAccess)
|
||||
mgr.DrawLighting = !mgr.DrawLighting;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -763,7 +748,7 @@ namespace Robust.Client.Console.Commands
|
||||
public string Description => "Run the GC.";
|
||||
public string Help => "gc [generation]";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (args.Length == 0)
|
||||
{
|
||||
@@ -774,10 +759,8 @@ namespace Robust.Client.Console.Commands
|
||||
if (int.TryParse(args[0], out int result))
|
||||
GC.Collect(result);
|
||||
else
|
||||
console.AddLine("Failed to parse argument.",Color.Red);
|
||||
shell.WriteLine("Failed to parse argument.",Color.Red);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -787,12 +770,10 @@ namespace Robust.Client.Console.Commands
|
||||
public string Description => "Run the GC, fully, compacting LOH and everything.";
|
||||
public string Help => "gcf";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
|
||||
GC.Collect(2, GCCollectionMode.Forced, true, true);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -805,16 +786,16 @@ namespace Robust.Client.Console.Commands
|
||||
|
||||
public string Help => "gc_mode\nSee current GC Latencymode\ngc_mode [type]\n Change GC Latency mode to [type]";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var prevMode = GCSettings.LatencyMode;
|
||||
if (args.Length == 0)
|
||||
{
|
||||
console.AddLine($"current gc latency mode: {(int) prevMode} ({prevMode})");
|
||||
console.AddLine("possible modes:");
|
||||
shell.WriteLine($"current gc latency mode: {(int) prevMode} ({prevMode})");
|
||||
shell.WriteLine("possible modes:");
|
||||
foreach (int mode in (int[]) Enum.GetValues(typeof(GCLatencyMode)))
|
||||
{
|
||||
console.AddLine($" {mode}: {Enum.GetName(typeof(GCLatencyMode), mode)}");
|
||||
shell.WriteLine($" {mode}: {Enum.GetName(typeof(GCLatencyMode), mode)}");
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -826,16 +807,14 @@ namespace Robust.Client.Console.Commands
|
||||
}
|
||||
else if (!Enum.TryParse(args[0], true, out mode))
|
||||
{
|
||||
console.AddLine($"unknown gc latency mode: {args[0]}");
|
||||
return false;
|
||||
shell.WriteLine($"unknown gc latency mode: {args[0]}");
|
||||
return;
|
||||
}
|
||||
|
||||
console.AddLine($"attempting gc latency mode change: {(int) prevMode} ({prevMode}) -> {(int) mode} ({mode})");
|
||||
shell.WriteLine($"attempting gc latency mode change: {(int) prevMode} ({prevMode}) -> {(int) mode} ({mode})");
|
||||
GCSettings.LatencyMode = mode;
|
||||
console.AddLine($"resulting gc latency mode: {(int) GCSettings.LatencyMode} ({GCSettings.LatencyMode})");
|
||||
shell.WriteLine($"resulting gc latency mode: {(int) GCSettings.LatencyMode} ({GCSettings.LatencyMode})");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -849,15 +828,13 @@ namespace Robust.Client.Console.Commands
|
||||
|
||||
public string Help => "szr_stats";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
|
||||
console.AddLine($"serialized: {RobustSerializer.BytesSerialized} bytes, {RobustSerializer.ObjectsSerialized} objects");
|
||||
console.AddLine($"largest serialized: {RobustSerializer.LargestObjectSerializedBytes} bytes, {RobustSerializer.LargestObjectSerializedType} objects");
|
||||
console.AddLine($"deserialized: {RobustSerializer.BytesDeserialized} bytes, {RobustSerializer.ObjectsDeserialized} objects");
|
||||
console.AddLine($"largest serialized: {RobustSerializer.LargestObjectDeserializedBytes} bytes, {RobustSerializer.LargestObjectDeserializedType} objects");
|
||||
|
||||
return false;
|
||||
shell.WriteLine($"serialized: {RobustSerializer.BytesSerialized} bytes, {RobustSerializer.ObjectsSerialized} objects");
|
||||
shell.WriteLine($"largest serialized: {RobustSerializer.LargestObjectSerializedBytes} bytes, {RobustSerializer.LargestObjectSerializedType} objects");
|
||||
shell.WriteLine($"deserialized: {RobustSerializer.BytesDeserialized} bytes, {RobustSerializer.ObjectsDeserialized} objects");
|
||||
shell.WriteLine($"largest serialized: {RobustSerializer.LargestObjectDeserializedBytes} bytes, {RobustSerializer.LargestObjectDeserializedType} objects");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -868,7 +845,7 @@ namespace Robust.Client.Console.Commands
|
||||
public string Description => "Gets info about a chunk under your mouse cursor.";
|
||||
public string Help => Command;
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var mapMan = IoCManager.Resolve<IMapManager>();
|
||||
var inputMan = IoCManager.Resolve<IInputManager>();
|
||||
@@ -878,8 +855,8 @@ namespace Robust.Client.Console.Commands
|
||||
|
||||
if (!mapMan.TryFindGridAt(mousePos, out var grid))
|
||||
{
|
||||
console.AddLine("No grid under your mouse cursor.");
|
||||
return false;
|
||||
shell.WriteLine("No grid under your mouse cursor.");
|
||||
return;
|
||||
}
|
||||
|
||||
var internalGrid = (IMapGridInternal)grid;
|
||||
@@ -887,8 +864,7 @@ namespace Robust.Client.Console.Commands
|
||||
var chunkIndex = grid.LocalToChunkIndices(grid.MapToGrid(mousePos));
|
||||
var chunk = internalGrid.GetChunk(chunkIndex);
|
||||
|
||||
console.AddLine($"worldBounds: {chunk.CalcWorldBounds()} localBounds: {chunk.CalcLocalBounds()}");
|
||||
return false;
|
||||
shell.WriteLine($"worldBounds: {chunk.CalcWorldBounds()} localBounds: {chunk.CalcLocalBounds()}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -905,7 +881,7 @@ namespace Robust.Client.Console.Commands
|
||||
|
||||
public static ConcurrentDictionary<string, bool>? _reloadShadersQueued = new();
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
IResourceCacheInternal resC;
|
||||
if (args.Length == 1)
|
||||
@@ -914,8 +890,8 @@ namespace Robust.Client.Console.Commands
|
||||
{
|
||||
if (_watchers != null)
|
||||
{
|
||||
console.AddLine("Already watching.");
|
||||
return false;
|
||||
shell.WriteLine("Already watching.");
|
||||
return;
|
||||
}
|
||||
resC = IoCManager.Resolve<IResourceCacheInternal>();
|
||||
|
||||
@@ -984,11 +960,11 @@ namespace Robust.Client.Console.Commands
|
||||
{
|
||||
IoCManager.Resolve<IResourceCache>()
|
||||
.ReloadResource<ShaderSourceResource>(resPath);
|
||||
console.AddLine($"Reloaded shader: {resPath}");
|
||||
shell.WriteLine($"Reloaded shader: {resPath}");
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
console.AddLine($"Failed to reload shader: {resPath}");
|
||||
shell.WriteLine($"Failed to reload shader: {resPath}");
|
||||
}
|
||||
|
||||
_reloadShadersQueued.TryRemove(ev.FullPath, out var _);
|
||||
@@ -1008,17 +984,17 @@ namespace Robust.Client.Console.Commands
|
||||
++created;
|
||||
}
|
||||
|
||||
console.AddLine($"Created {created} shader directory watchers for {shaderCount} shaders.");
|
||||
shell.WriteLine($"Created {created} shader directory watchers for {shaderCount} shaders.");
|
||||
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (args[0] == "-watch")
|
||||
{
|
||||
if (_watchers == null)
|
||||
{
|
||||
console.AddLine("No shader directory watchers active.");
|
||||
return false;
|
||||
shell.WriteLine("No shader directory watchers active.");
|
||||
return;
|
||||
}
|
||||
|
||||
var disposed = 0;
|
||||
@@ -1030,19 +1006,19 @@ namespace Robust.Client.Console.Commands
|
||||
|
||||
_watchers = null;
|
||||
|
||||
console.AddLine($"Disposed of {disposed} shader directory watchers.");
|
||||
shell.WriteLine($"Disposed of {disposed} shader directory watchers.");
|
||||
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (args.Length > 1)
|
||||
{
|
||||
console.AddLine("Not implemented.");
|
||||
return false;
|
||||
shell.WriteLine("Not implemented.");
|
||||
return;
|
||||
}
|
||||
|
||||
console.AddLine("Reloading content shader resources...");
|
||||
shell.WriteLine("Reloading content shader resources...");
|
||||
|
||||
resC = IoCManager.Resolve<IResourceCacheInternal>();
|
||||
|
||||
@@ -1054,13 +1030,11 @@ namespace Robust.Client.Console.Commands
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
console.AddLine($"Failed to reload shader: {path}");
|
||||
shell.WriteLine($"Failed to reload shader: {path}");
|
||||
}
|
||||
}
|
||||
|
||||
console.AddLine("Done.");
|
||||
|
||||
return false;
|
||||
shell.WriteLine("Done.");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1071,14 +1045,14 @@ namespace Robust.Client.Console.Commands
|
||||
public string Description => "Toggle fov and light debug layers";
|
||||
public string Help => "cldbglyr <layer>: Toggle <layer>\ncldbglyr: Turn all Layers off";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var clyde = IoCManager.Resolve<IClydeInternal>();
|
||||
|
||||
if (args.Length < 1)
|
||||
{
|
||||
clyde.DebugLayers = ClydeDebugLayers.None;
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
clyde.DebugLayers = args[0] switch
|
||||
@@ -1087,8 +1061,6 @@ namespace Robust.Client.Console.Commands
|
||||
"light" => ClydeDebugLayers.Light,
|
||||
_ => ClydeDebugLayers.None
|
||||
};
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1098,12 +1070,12 @@ namespace Robust.Client.Console.Commands
|
||||
public string Description => "Keys key info for a key";
|
||||
public string Help => "keyinfo <Key>";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (args.Length != 1)
|
||||
{
|
||||
console.AddLine(Help);
|
||||
return false;
|
||||
shell.WriteLine(Help);
|
||||
return;
|
||||
}
|
||||
|
||||
var clyde = IoCManager.Resolve<IClydeInternal>();
|
||||
@@ -1116,15 +1088,13 @@ namespace Robust.Client.Console.Commands
|
||||
var scanCode = clyde.GetKeyScanCode(key);
|
||||
var nameScanCode = clyde.GetKeyNameScanCode(scanCode);
|
||||
|
||||
console.AddLine($"name: '{name}' scan code: '{scanCode}' name via scan code: '{nameScanCode}'");
|
||||
shell.WriteLine($"name: '{name}' scan code: '{scanCode}' name via scan code: '{nameScanCode}'");
|
||||
}
|
||||
else if (int.TryParse(args[0], out var scanCode))
|
||||
{
|
||||
var nameScanCode = clyde.GetKeyNameScanCode(scanCode);
|
||||
console.AddLine($"name via scan code: '{nameScanCode}'");
|
||||
shell.WriteLine($"name via scan code: '{nameScanCode}'");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using System;
|
||||
using Robust.Client.Interfaces.Console;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.ContentPack;
|
||||
using Robust.Shared.Maths;
|
||||
|
||||
@@ -12,23 +12,21 @@ namespace Robust.Client.Console.Commands
|
||||
public string Description => "Dumps a type's members in a format suitable for the sandbox configuration file.";
|
||||
public string Help => "Usage: dmetamem <type>";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var type = Type.GetType(args[0]);
|
||||
|
||||
if (type == null)
|
||||
{
|
||||
console.AddLine("That type does not exist", Color.Red);
|
||||
return false;
|
||||
shell.WriteLine("That type does not exist", Color.Red);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var sig in AssemblyTypeChecker.DumpMetaMembers(type))
|
||||
{
|
||||
System.Console.WriteLine(@$"- ""{sig}""");
|
||||
console.AddLine(sig);
|
||||
shell.WriteLine(sig);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using System.Linq;
|
||||
using Robust.Client.Interfaces.Console;
|
||||
using System.Linq;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.Interfaces.Network;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Maths;
|
||||
@@ -12,37 +12,36 @@ namespace Robust.Client.Console.Commands
|
||||
public string Help => "When no arguments are provided, displays a generic help text. When an argument is passed, display the help text for the command with that name.";
|
||||
public string Description => "Display help text.";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
switch (args.Length)
|
||||
{
|
||||
case 0:
|
||||
console.AddLine("To display help for a specific command, write 'help <command>'. To list all available commands, write 'list'.");
|
||||
shell.WriteLine("To display help for a specific command, write 'help <command>'. To list all available commands, write 'list'.");
|
||||
break;
|
||||
|
||||
case 1:
|
||||
string commandname = args[0];
|
||||
if (!console.Commands.ContainsKey(commandname))
|
||||
if (!shell.ConsoleHost.RegisteredCommands.ContainsKey(commandname))
|
||||
{
|
||||
if (!IoCManager.Resolve<IClientNetManager>().IsConnected)
|
||||
{
|
||||
// No server so nothing to respond with unknown command.
|
||||
console.AddLine("Unknown command: " + commandname, Color.Red);
|
||||
return false;
|
||||
shell.WriteLine("Unknown command: " + commandname, Color.Red);
|
||||
return;
|
||||
}
|
||||
// TODO: Maybe have a server side help?
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
IConsoleCommand command = console.Commands[commandname];
|
||||
console.AddLine(string.Format("{0} - {1}", command.Command, command.Description));
|
||||
console.AddLine(command.Help);
|
||||
IConsoleCommand command = shell.ConsoleHost.RegisteredCommands[commandname];
|
||||
shell.WriteLine(string.Format("{0} - {1}", command.Command, command.Description));
|
||||
shell.WriteLine(command.Help);
|
||||
break;
|
||||
|
||||
default:
|
||||
console.AddLine("Invalid amount of arguments.", Color.Red);
|
||||
shell.WriteLine("Invalid amount of arguments.", Color.Red);
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +54,7 @@ namespace Robust.Client.Console.Commands
|
||||
"only commands that contain the given string in their name will be listed.";
|
||||
public string Description => "List all commands, optionally with a filter.";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var filter = "";
|
||||
if (args.Length == 1)
|
||||
@@ -64,14 +63,12 @@ namespace Robust.Client.Console.Commands
|
||||
}
|
||||
|
||||
var conGroup = IoCManager.Resolve<IClientConGroupController>();
|
||||
foreach (var command in console.Commands.Values
|
||||
foreach (var command in shell.ConsoleHost.RegisteredCommands.Values
|
||||
.Where(p => p.Command.Contains(filter) && conGroup.CanCommand(p.Command))
|
||||
.OrderBy(c => c.Command))
|
||||
{
|
||||
console.AddLine(command.Command + ": " + command.Description);
|
||||
shell.WriteLine(command.Command + ": " + command.Description);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,9 +3,9 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Robust.Client.Interfaces.Console;
|
||||
using Robust.Client.Utility;
|
||||
using Robust.Shared;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.Interfaces.Configuration;
|
||||
using Robust.Shared.IoC;
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Robust.Client.Console.Commands
|
||||
public string Description => "Load authentication tokens from launcher data to aid in testing of live servers";
|
||||
public string Help => "launchauth [account name]";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var wantName = args.Length > 0 ? args[0] : null;
|
||||
|
||||
@@ -32,8 +32,8 @@ namespace Robust.Client.Console.Commands
|
||||
|
||||
if (login == null)
|
||||
{
|
||||
console.AddLine("Unable to find a matching login");
|
||||
return false;
|
||||
shell.WriteLine("Unable to find a matching login");
|
||||
return;
|
||||
}
|
||||
|
||||
var token = login.Token.Token;
|
||||
@@ -42,8 +42,6 @@ namespace Robust.Client.Console.Commands
|
||||
var cfg = IoCManager.Resolve<IConfigurationManagerInternal>();
|
||||
cfg.SetSecureCVar(CVars.AuthUserId, userId);
|
||||
cfg.SetSecureCVar(CVars.AuthToken, token);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private sealed class LauncherConfig
|
||||
|
||||
@@ -2,7 +2,7 @@ using System.Linq;
|
||||
using System.Runtime.Loader;
|
||||
using System.Text;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.Interfaces.Console;
|
||||
using Robust.Shared.Console;
|
||||
|
||||
namespace Robust.Client.Console.Commands
|
||||
{
|
||||
@@ -13,18 +13,16 @@ namespace Robust.Client.Console.Commands
|
||||
public string Description => "Lists loaded assemblies by load context.";
|
||||
public string Help => Command;
|
||||
|
||||
public bool Execute(IDebugConsole console, string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
foreach (var context in AssemblyLoadContext.All)
|
||||
{
|
||||
console.AddLine($"{context.Name}:");
|
||||
shell.WriteLine($"{context.Name}:");
|
||||
foreach (var assembly in context.Assemblies.OrderBy(a => a.FullName))
|
||||
{
|
||||
console.AddLine($" {assembly.FullName}");
|
||||
shell.WriteLine($" {assembly.FullName}");
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using Robust.Client.Interfaces.Console;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Maths;
|
||||
using System;
|
||||
using Robust.Shared.Console;
|
||||
|
||||
namespace Robust.Client.Console.Commands
|
||||
{
|
||||
@@ -13,12 +13,12 @@ namespace Robust.Client.Console.Commands
|
||||
+ "\n sawmill: A label prefixing log messages. This is the one you're setting the level for."
|
||||
+ "\n level: The log level. Must match one of the values of the LogLevel enum.";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (args.Length != 2)
|
||||
{
|
||||
console.AddLine("Invalid argument amount. Expected 2 arguments.", Color.Red);
|
||||
return false;
|
||||
shell.WriteLine("Invalid argument amount. Expected 2 arguments.", Color.Red);
|
||||
return;
|
||||
}
|
||||
|
||||
var name = args[0];
|
||||
@@ -32,13 +32,12 @@ namespace Robust.Client.Console.Commands
|
||||
{
|
||||
if (!Enum.TryParse<LogLevel>(levelname, out var result))
|
||||
{
|
||||
console.AddLine("Failed to parse 2nd argument. Must be one of the values of the LogLevel enum.");
|
||||
return false;
|
||||
shell.WriteLine("Failed to parse 2nd argument. Must be one of the values of the LogLevel enum.");
|
||||
return;
|
||||
}
|
||||
level = result;
|
||||
}
|
||||
Logger.GetSawmill(name).Level = level;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,12 +50,12 @@ namespace Robust.Client.Console.Commands
|
||||
+ "\n level: The log level. Must match one of the values of the LogLevel enum."
|
||||
+ "\n message: The message to be logged. Wrap this in double quotes if you want to use spaces.";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (args.Length != 3)
|
||||
{
|
||||
console.AddLine("Invalid argument amount. Expected 3 arguments.", Color.Red);
|
||||
return false;
|
||||
shell.WriteLine("Invalid argument amount. Expected 3 arguments.", Color.Red);
|
||||
return;
|
||||
}
|
||||
|
||||
var name = args[0];
|
||||
@@ -64,13 +63,12 @@ namespace Robust.Client.Console.Commands
|
||||
var message = args[2]; // yes this doesn't support spaces idgaf.
|
||||
if (!Enum.TryParse<LogLevel>(levelname, out var result))
|
||||
{
|
||||
console.AddLine("Failed to parse 2nd argument. Must be one of the values of the LogLevel enum.");
|
||||
return false;
|
||||
shell.WriteLine("Failed to parse 2nd argument. Must be one of the values of the LogLevel enum.");
|
||||
return;
|
||||
}
|
||||
var level = result;
|
||||
|
||||
Logger.LogS(level, name, message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using Robust.Client.Interfaces.Console;
|
||||
using System;
|
||||
using Robust.Shared.Console;
|
||||
|
||||
namespace Robust.Client.Console.Commands
|
||||
{
|
||||
@@ -9,10 +9,9 @@ namespace Robust.Client.Console.Commands
|
||||
public string Description => "Kills the game client instantly.";
|
||||
public string Help => "Kills the game client instantly, leaving no traces. No telling the server goodbye";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
Environment.Exit(0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Robust.Client.Interfaces.Console;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Maths;
|
||||
@@ -6,17 +6,15 @@ using Robust.Shared.Maths;
|
||||
namespace Robust.Client.Console.Commands
|
||||
{
|
||||
#if CLIENT_SCRIPTING
|
||||
internal sealed class ScriptConsoleCommand : IConsoleCommand
|
||||
internal sealed class ScriptCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "csi";
|
||||
public string Description => "Opens a C# interactive console.";
|
||||
public string Help => "csi";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
new ScriptConsoleClient().OpenCentered();
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,33 +24,29 @@ namespace Robust.Client.Console.Commands
|
||||
public string Description => "Opens a variable watch window.";
|
||||
public string Help => "watch";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
new WatchWindow().OpenCentered();
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
internal sealed class ServerScriptConsoleCommand : IConsoleCommand
|
||||
internal sealed class ServerScriptCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "scsi";
|
||||
public string Description => "Opens a C# interactive console on the server.";
|
||||
public string Help => "scsi";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var mgr = IoCManager.Resolve<IScriptClient>();
|
||||
if (!mgr.CanScript)
|
||||
{
|
||||
console.AddLine(Loc.GetString("You do not have server side scripting permission."), Color.Red);
|
||||
return false;
|
||||
shell.WriteLine(Loc.GetString("You do not have server side scripting permission."), Color.Red);
|
||||
return;
|
||||
}
|
||||
|
||||
mgr.StartSession();
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Robust.Client.Interfaces.Console;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.Interfaces.Network;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Network;
|
||||
@@ -11,7 +11,7 @@ namespace Robust.Client.Console.Commands
|
||||
public string Description => "Sends garbage to the server.";
|
||||
public string Help => "The server will reply with 'no u'";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
// MsgStringTableEntries is registered as NetMessageAccept.Client so the server will immediately deny it.
|
||||
// And kick us.
|
||||
@@ -19,8 +19,6 @@ namespace Robust.Client.Console.Commands
|
||||
var msg = net.CreateNetMessage<MsgStringTableEntries>();
|
||||
msg.Entries = new MsgStringTableEntries.Entry[0];
|
||||
net.ClientSendMessage(msg);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.Interfaces.Console;
|
||||
using Robust.Client.Interfaces.Input;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.IoC;
|
||||
|
||||
namespace Robust.Client.Console.Commands
|
||||
@@ -12,24 +12,23 @@ namespace Robust.Client.Console.Commands
|
||||
public string Description => "Sets the active input context.";
|
||||
public string Help => "setinputcontext <context>";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (args.Length != 1)
|
||||
{
|
||||
console.AddLine("Invalid number of arguments!");
|
||||
return false;
|
||||
shell.WriteLine("Invalid number of arguments!");
|
||||
return;
|
||||
}
|
||||
|
||||
var inputMan = IoCManager.Resolve<IInputManager>();
|
||||
|
||||
if (!inputMan.Contexts.Exists(args[0]))
|
||||
{
|
||||
console.AddLine("Context not found!");
|
||||
return false;
|
||||
shell.WriteLine("Context not found!");
|
||||
return;
|
||||
}
|
||||
|
||||
inputMan.Contexts.SetActiveContext(args[0]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Robust.Client.Interfaces.Console;
|
||||
|
||||
namespace Robust.Client.Console
|
||||
{
|
||||
public interface IClientConsole : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes the console into a useable state.
|
||||
/// </summary>
|
||||
void Initialize();
|
||||
|
||||
/// <summary>
|
||||
/// Resets the console to a post-initialized state.
|
||||
/// </summary>
|
||||
void Reset();
|
||||
|
||||
|
||||
event EventHandler<AddStringArgs> AddString;
|
||||
event EventHandler<AddFormattedMessageArgs> AddFormatted;
|
||||
event EventHandler ClearText;
|
||||
|
||||
IReadOnlyDictionary<string, IConsoleCommand> Commands { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Parses console commands (verbs).
|
||||
/// </summary>
|
||||
/// <param name="text"></param>
|
||||
void ProcessCommand(string text);
|
||||
|
||||
void SendServerCommandRequest();
|
||||
}
|
||||
}
|
||||
24
Robust.Client/Console/IClientConsoleHost.cs
Normal file
24
Robust.Client/Console/IClientConsoleHost.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Robust.Client.Console
|
||||
{
|
||||
public interface IClientConsoleHost : IConsoleHost, IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes the console into a useable state.
|
||||
/// </summary>
|
||||
void Initialize();
|
||||
|
||||
/// <summary>
|
||||
/// Resets the console to a post-initialized state.
|
||||
/// </summary>
|
||||
void Reset();
|
||||
|
||||
event EventHandler<AddStringArgs> AddString;
|
||||
event EventHandler<AddFormattedMessageArgs> AddFormatted;
|
||||
|
||||
void AddFormattedLine(FormattedMessage message);
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ using Robust.Client.Interfaces.ResourceManagement;
|
||||
using Robust.Client.ResourceManagement;
|
||||
using Robust.Shared.GameObjects.Components;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.Interfaces.Physics;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Physics;
|
||||
@@ -26,6 +27,7 @@ namespace Robust.Client.Debugging
|
||||
[Dependency] private readonly IComponentManager _componentManager = default!;
|
||||
[Dependency] private readonly IEyeManager _eyeManager = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly IPhysicsManager _physicsManager = default!;
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
[Dependency] private readonly IInputManager _inputManager = default!;
|
||||
|
||||
@@ -48,7 +50,7 @@ namespace Robust.Client.Debugging
|
||||
if (value)
|
||||
{
|
||||
_overlayManager.AddOverlay(new PhysicsOverlay(_componentManager, _eyeManager,
|
||||
_prototypeManager, _inputManager));
|
||||
_prototypeManager, _inputManager, _physicsManager));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -86,6 +88,7 @@ namespace Robust.Client.Debugging
|
||||
private readonly IComponentManager _componentManager;
|
||||
private readonly IEyeManager _eyeManager;
|
||||
private readonly IInputManager _inputManager;
|
||||
private readonly IPhysicsManager _physicsManager;
|
||||
|
||||
public override OverlaySpace Space => OverlaySpace.WorldSpace | OverlaySpace.ScreenSpace;
|
||||
private readonly ShaderInstance _shader;
|
||||
@@ -94,12 +97,13 @@ namespace Robust.Client.Debugging
|
||||
private Vector2 _hoverStartScreen = Vector2.Zero;
|
||||
private List<IPhysBody> _hoverBodies = new();
|
||||
|
||||
public PhysicsOverlay(IComponentManager compMan, IEyeManager eyeMan, IPrototypeManager protoMan, IInputManager inputManager)
|
||||
public PhysicsOverlay(IComponentManager compMan, IEyeManager eyeMan, IPrototypeManager protoMan, IInputManager inputManager, IPhysicsManager physicsManager)
|
||||
: base(nameof(PhysicsOverlay))
|
||||
{
|
||||
_componentManager = compMan;
|
||||
_eyeManager = eyeMan;
|
||||
_inputManager = inputManager;
|
||||
_physicsManager = physicsManager;
|
||||
|
||||
_shader = protoMan.Index<ShaderPrototype>("unshaded").Instance();
|
||||
var cache = IoCManager.Resolve<IResourceCache>();
|
||||
@@ -158,23 +162,20 @@ namespace Robust.Client.Debugging
|
||||
_hoverStartScreen = mouseScreenPos;
|
||||
|
||||
var viewport = _eyeManager.GetWorldViewport();
|
||||
foreach (var boundingBox in _componentManager.EntityQuery<IPhysicsComponent>())
|
||||
{
|
||||
var physBody = (IPhysBody) boundingBox;
|
||||
|
||||
if (viewport.IsEmpty()) return;
|
||||
|
||||
var mapId = _eyeManager.CurrentMap;
|
||||
|
||||
foreach (var physBody in _physicsManager.GetCollidingEntities(mapId, viewport))
|
||||
{
|
||||
// all entities have a TransformComponent
|
||||
var transform = physBody.Entity.Transform;
|
||||
|
||||
// if not on the same map, continue
|
||||
if (transform.MapID != _eyeManager.CurrentMap || !transform.IsMapTransform)
|
||||
continue;
|
||||
|
||||
var worldBox = physBody.WorldAABB;
|
||||
var colorEdge = Color.Red.WithAlpha(0.33f);
|
||||
if (worldBox.IsEmpty()) continue;
|
||||
|
||||
// if not on screen, or too small, continue
|
||||
if (!worldBox.Intersects(in viewport) || worldBox.IsEmpty())
|
||||
continue;
|
||||
var colorEdge = Color.Red.WithAlpha(0.33f);
|
||||
|
||||
foreach (var shape in physBody.PhysicsShapes)
|
||||
{
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace Robust.Client
|
||||
[Dependency] private readonly IUserInterfaceManagerInternal _userInterfaceManager = default!;
|
||||
[Dependency] private readonly IBaseClient _client = default!;
|
||||
[Dependency] private readonly IInputManager _inputManager = default!;
|
||||
[Dependency] private readonly IClientConsole _console = default!;
|
||||
[Dependency] private readonly IClientConsoleHost _consoleHost = default!;
|
||||
[Dependency] private readonly ITimerManager _timerManager = default!;
|
||||
[Dependency] private readonly IClientEntityManager _entityManager = default!;
|
||||
[Dependency] private readonly IPlacementManager _placementManager = default!;
|
||||
@@ -167,7 +167,7 @@ namespace Robust.Client
|
||||
IoCManager.Resolve<INetConfigurationManager>().SetupNetworking();
|
||||
_serializer.Initialize();
|
||||
_inputManager.Initialize();
|
||||
_console.Initialize();
|
||||
_consoleHost.Initialize();
|
||||
_prototypeManager.LoadDirectory(new ResourcePath(@"/Prototypes/"));
|
||||
_prototypeManager.Resync();
|
||||
_mapManager.Initialize();
|
||||
|
||||
@@ -55,15 +55,13 @@ namespace Robust.Client.GameObjects
|
||||
|
||||
Register<AppearanceComponent>();
|
||||
RegisterReference<AppearanceComponent, SharedAppearanceComponent>();
|
||||
|
||||
|
||||
Register<AppearanceTestComponent>();
|
||||
Register<SnapGridComponent>();
|
||||
|
||||
Register<ClientUserInterfaceComponent>();
|
||||
RegisterReference<ClientUserInterfaceComponent, SharedUserInterfaceComponent>();
|
||||
|
||||
RegisterIgnore("IgnorePause");
|
||||
|
||||
Register<AnimationPlayerComponent>();
|
||||
|
||||
Register<ContainerManagerComponent>();
|
||||
|
||||
@@ -31,11 +31,11 @@ namespace Robust.Client.GameObjects
|
||||
}
|
||||
}
|
||||
|
||||
private static IDirectionalTextureProvider TextureForConfig(ObjectSerializer serializer, IResourceCache resourceCache)
|
||||
private static IRsiStateLike TextureForConfig(ObjectSerializer serializer, IResourceCache resourceCache)
|
||||
{
|
||||
DebugTools.Assert(serializer.Reading);
|
||||
|
||||
if (serializer.TryGetCacheData<IDirectionalTextureProvider>(SerializationCache, out var dirTex))
|
||||
if (serializer.TryGetCacheData<IRsiStateLike>(SerializationCache, out var dirTex))
|
||||
{
|
||||
return dirTex;
|
||||
}
|
||||
@@ -93,7 +93,7 @@ namespace Robust.Client.GameObjects
|
||||
}
|
||||
}
|
||||
|
||||
public static IDirectionalTextureProvider? GetPrototypeIcon(EntityPrototype prototype, IResourceCache resourceCache)
|
||||
public static IRsiStateLike? GetPrototypeIcon(EntityPrototype prototype, IResourceCache resourceCache)
|
||||
{
|
||||
if (!prototype.Components.TryGetValue("Icon", out var mapping))
|
||||
{
|
||||
|
||||
12
Robust.Client/GameObjects/Components/IgnorePauseComponent.cs
Normal file
12
Robust.Client/GameObjects/Components/IgnorePauseComponent.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameObjects.Components;
|
||||
|
||||
namespace Robust.Client.GameObjects.Components
|
||||
{
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(SharedIgnorePauseComponent))]
|
||||
public sealed class IgnorePauseComponent : SharedIgnorePauseComponent
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1046,7 +1046,7 @@ namespace Robust.Client.GameObjects
|
||||
var rsi = layer.RSI ?? BaseRSI;
|
||||
if (rsi == null || !rsi.TryGetState(layer.State, out var state))
|
||||
{
|
||||
state = GetFallbackState();
|
||||
state = GetFallbackState(resourceCache);
|
||||
}
|
||||
|
||||
var layerSpecificDir = layer.EffectiveDirection(state, worldRotation, overrideDirection);
|
||||
@@ -1279,7 +1279,7 @@ namespace Robust.Client.GameObjects
|
||||
var rsi = layer.RSI ?? BaseRSI;
|
||||
if (rsi == null || !rsi.TryGetState(layer.State, out var state))
|
||||
{
|
||||
state = GetFallbackState();
|
||||
state = GetFallbackState(resourceCache);
|
||||
}
|
||||
|
||||
if (!state.IsAnimated)
|
||||
@@ -1407,7 +1407,7 @@ namespace Robust.Client.GameObjects
|
||||
var rsi = layer.RSI ?? BaseRSI;
|
||||
if (rsi == null || !rsi.TryGetState(layer.State, out var state))
|
||||
{
|
||||
state = GetFallbackState();
|
||||
state = GetFallbackState(resourceCache);
|
||||
}
|
||||
|
||||
if (state.IsAnimated)
|
||||
@@ -1418,9 +1418,9 @@ namespace Robust.Client.GameObjects
|
||||
}
|
||||
}
|
||||
|
||||
private RSI.State GetFallbackState()
|
||||
internal static RSI.State GetFallbackState(IResourceCache cache)
|
||||
{
|
||||
var rsi = resourceCache.GetResource<RSIResource>("/Textures/error.rsi").RSI;
|
||||
var rsi = cache.GetResource<RSIResource>("/Textures/error.rsi").RSI;
|
||||
return rsi["error"];
|
||||
}
|
||||
|
||||
@@ -1738,14 +1738,14 @@ namespace Robust.Client.GameObjects
|
||||
var rsi = ActualRsi;
|
||||
if (rsi == null)
|
||||
{
|
||||
state = _parent.GetFallbackState();
|
||||
state = GetFallbackState(_parent.resourceCache);
|
||||
Logger.ErrorS(LogCategory, "No RSI to pull new state from! Trace:\n{0}", Environment.StackTrace);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!rsi.TryGetState(stateId, out state))
|
||||
{
|
||||
state = _parent.GetFallbackState();
|
||||
state = GetFallbackState(_parent.resourceCache);
|
||||
Logger.ErrorS(LogCategory, "State '{0}' does not exist in RSI. Trace:\n{1}", stateId,
|
||||
Environment.StackTrace);
|
||||
}
|
||||
@@ -1796,7 +1796,7 @@ namespace Robust.Client.GameObjects
|
||||
}
|
||||
}
|
||||
|
||||
public IDirectionalTextureProvider? Icon
|
||||
public IRsiStateLike? Icon
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -1806,13 +1806,13 @@ namespace Robust.Client.GameObjects
|
||||
|
||||
var texture = layer.Texture;
|
||||
|
||||
if (!layer.State.IsValid) return null;
|
||||
if (!layer.State.IsValid) return texture;
|
||||
|
||||
// Pull texture from RSI state instead.
|
||||
var rsi = layer.RSI ?? BaseRSI;
|
||||
if (rsi == null || !rsi.TryGetState(layer.State, out var state))
|
||||
{
|
||||
state = GetFallbackState();
|
||||
state = GetFallbackState(resourceCache);
|
||||
}
|
||||
|
||||
return state;
|
||||
@@ -1870,21 +1870,21 @@ namespace Robust.Client.GameObjects
|
||||
|
||||
}
|
||||
|
||||
public static IDirectionalTextureProvider? GetPrototypeIcon(EntityPrototype prototype, IResourceCache resourceCache)
|
||||
public static IRsiStateLike GetPrototypeIcon(EntityPrototype prototype, IResourceCache resourceCache)
|
||||
{
|
||||
var icon = IconComponent.GetPrototypeIcon(prototype, resourceCache);
|
||||
if (icon != null) return icon;
|
||||
|
||||
if (!prototype.Components.TryGetValue("Sprite", out var spriteNode))
|
||||
if (!prototype.Components.ContainsKey("Sprite"))
|
||||
{
|
||||
return resourceCache.GetFallback<TextureResource>().Texture;
|
||||
return GetFallbackState(resourceCache);
|
||||
}
|
||||
|
||||
var dummy = new DummyIconEntity() {Prototype = prototype};
|
||||
var dummy = new DummyIconEntity {Prototype = prototype};
|
||||
var spriteComponent = dummy.AddComponent<SpriteComponent>();
|
||||
dummy.Delete();
|
||||
|
||||
return spriteComponent?.Icon ?? resourceCache.GetFallback<TextureResource>().Texture;
|
||||
return spriteComponent.Icon ?? GetFallbackState(resourceCache);
|
||||
}
|
||||
|
||||
#region DummyIconEntity
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace Robust.Client.GameObjects.EntitySystems
|
||||
{
|
||||
public override void FrameUpdate(float frameTime)
|
||||
{
|
||||
foreach (var animationPlayerComponent in EntityManager.ComponentManager.EntityQuery<AnimationPlayerComponent>())
|
||||
foreach (var animationPlayerComponent in EntityManager.ComponentManager.EntityQuery<AnimationPlayerComponent>(true))
|
||||
{
|
||||
animationPlayerComponent.Update(frameTime);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace Robust.Client.GameObjects.EntitySystems
|
||||
{
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
foreach (var appearanceTestComponent in EntityManager.ComponentManager.EntityQuery<AppearanceTestComponent>())
|
||||
foreach (var appearanceTestComponent in EntityManager.ComponentManager.EntityQuery<AppearanceTestComponent>(true))
|
||||
{
|
||||
appearanceTestComponent.OnUpdate(frameTime);
|
||||
}
|
||||
|
||||
@@ -56,12 +56,12 @@ namespace Robust.Client.GameObjects.EntitySystems
|
||||
|
||||
private void PlayAudioPositionalHandler(PlayAudioPositionalMessage ev)
|
||||
{
|
||||
var gridId = ev.Coordinates.GetGridId(_entityManager);
|
||||
|
||||
if (!_mapManager.GridExists(gridId))
|
||||
var mapId = ev.Coordinates.GetMapId(_entityManager);
|
||||
|
||||
if (!_mapManager.MapExists(mapId))
|
||||
{
|
||||
Logger.Error(
|
||||
$"Server tried to play sound on grid {gridId}, which does not exist. Ignoring.");
|
||||
$"Server tried to play sound on map {mapId}, which does not exist. Ignoring.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -111,13 +111,13 @@ namespace Robust.Client.GameObjects.EntitySystems
|
||||
if (stream.TrackingCoordinates != null)
|
||||
{
|
||||
var coords = stream.TrackingCoordinates.Value;
|
||||
if (_mapManager.GridExists(coords.GetGridId(_entityManager)))
|
||||
if (_mapManager.MapExists(coords.GetMapId(_entityManager)))
|
||||
{
|
||||
mapPos = stream.TrackingCoordinates.Value.ToMap(_entityManager);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Grid no longer exists, delete stream.
|
||||
// Map no longer exists, delete stream.
|
||||
StreamDone(stream);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Graphics.Drawing;
|
||||
using Robust.Client.Interfaces.Graphics.ClientEye;
|
||||
using Robust.Client.Interfaces.ResourceManagement;
|
||||
@@ -57,47 +57,54 @@ namespace Robust.Client.GameObjects
|
||||
|
||||
public void CreateEffect(EffectSystemMessage message)
|
||||
{
|
||||
// The source of effects is either local actions during FirstTimePredicted, or the network at LastServerTick
|
||||
// When replaying predicted input, don't spam effects.
|
||||
if(gameTiming.InPrediction && !gameTiming.IsFirstTimePredicted)
|
||||
return;
|
||||
|
||||
if (message.AttachedEntityUid != null && message.Coordinates != default)
|
||||
{
|
||||
Logger.Warning("Set both an AttachedEntityUid and EntityCoordinates on an EffectSystemMessage for sprite {0} which is not supported!", message.EffectSprite);
|
||||
}
|
||||
|
||||
var gameTime = gameTiming.CurTime;
|
||||
if (gameTime > message.DeathTime) //Did we already die in transit? That's pretty troubling isn't it
|
||||
if (message.LifeTime <= TimeSpan.Zero)
|
||||
{
|
||||
Logger.Warning("Effect using sprite {0} died in transit to the client", message.EffectSprite);
|
||||
Logger.Warning("Effect using sprite {0} had zero lifetime.", message.EffectSprite);
|
||||
return;
|
||||
}
|
||||
|
||||
//Create effect from creation message
|
||||
var effect = new Effect(message, resourceCache, _mapManager, _entityManager);
|
||||
effect.Deathtime = gameTiming.CurTime + message.LifeTime;
|
||||
if (effect.AttachedEntityUid != null)
|
||||
{
|
||||
effect.AttachedEntity = _entityManager.GetEntity(effect.AttachedEntityUid.Value);
|
||||
}
|
||||
|
||||
//Age the effect through a single update to the previous update tick of the effect system
|
||||
//effect.Update((float)((lasttimeprocessed - effect.Age).TotalSeconds));
|
||||
|
||||
_Effects.Add(effect);
|
||||
}
|
||||
|
||||
public override void FrameUpdate(float frameTime)
|
||||
{
|
||||
var curTime = gameTiming.CurTime;
|
||||
for (int i = 0; i < _Effects.Count; i++)
|
||||
{
|
||||
var effect = _Effects[i];
|
||||
|
||||
//Update variables of the effect via its deltas
|
||||
effect.Update(frameTime);
|
||||
|
||||
//These effects have died
|
||||
if (effect.Age > effect.Deathtime)
|
||||
// Effects are purely visual, so they don't need to be ran through prediction.
|
||||
// once CurTime ever passes DeathTime (clients render the top at IsFirstTimePredicted, where this happens) just remove them.
|
||||
if (curTime > effect.Deathtime)
|
||||
{
|
||||
//Remove from the effects list and decrement the iterator
|
||||
_Effects.Remove(effect);
|
||||
i--;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Update variables of the effect via its deltas
|
||||
effect.Update(frameTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,14 +212,9 @@ namespace Robust.Client.GameObjects
|
||||
public bool Shaded = true;
|
||||
|
||||
/// <summary>
|
||||
/// Effect's age -- from 0f
|
||||
/// CurTime after which the effect will "die"
|
||||
/// </summary>
|
||||
public TimeSpan Age = TimeSpan.Zero;
|
||||
|
||||
/// <summary>
|
||||
/// Time after which the effect will "die"
|
||||
/// </summary>
|
||||
public TimeSpan Deathtime = TimeSpan.FromSeconds(1);
|
||||
public TimeSpan Deathtime;
|
||||
|
||||
private readonly IMapManager _mapManager;
|
||||
private readonly IEntityManager _entityManager;
|
||||
@@ -245,8 +247,6 @@ namespace Robust.Client.GameObjects
|
||||
RadialAcceleration = effectcreation.RadialAcceleration;
|
||||
TangentialVelocity = effectcreation.TangentialVelocity;
|
||||
TangentialAcceleration = effectcreation.TangentialAcceleration;
|
||||
Age = effectcreation.Born;
|
||||
Deathtime = effectcreation.DeathTime;
|
||||
Rotation = effectcreation.Rotation;
|
||||
RotationRate = effectcreation.RotationRate;
|
||||
Size = effectcreation.Size;
|
||||
@@ -260,10 +260,6 @@ namespace Robust.Client.GameObjects
|
||||
|
||||
public void Update(float frameTime)
|
||||
{
|
||||
Age += TimeSpan.FromSeconds(frameTime);
|
||||
if (Age >= Deathtime)
|
||||
return;
|
||||
|
||||
Velocity += Acceleration * frameTime;
|
||||
RadialVelocity += RadialAcceleration * frameTime;
|
||||
TangentialVelocity += TangentialAcceleration * frameTime;
|
||||
|
||||
@@ -87,7 +87,7 @@ namespace Robust.Client.GameObjects.EntitySystems
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var eyeComponent in EntityManager.ComponentManager.EntityQuery<EyeComponent>())
|
||||
foreach (var eyeComponent in EntityManager.ComponentManager.EntityQuery<EyeComponent>(true))
|
||||
{
|
||||
eyeComponent.UpdateEyePosition();
|
||||
}
|
||||
|
||||
262
Robust.Client/GameStates/NetEntityOverlay.cs
Normal file
262
Robust.Client/GameStates/NetEntityOverlay.cs
Normal file
@@ -0,0 +1,262 @@
|
||||
using System.Collections.Generic;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Graphics.Drawing;
|
||||
using Robust.Client.Graphics.Overlays;
|
||||
using Robust.Client.Interfaces.GameStates;
|
||||
using Robust.Client.Interfaces.Graphics.ClientEye;
|
||||
using Robust.Client.Interfaces.Graphics.Overlays;
|
||||
using Robust.Client.Interfaces.ResourceManagement;
|
||||
using Robust.Client.ResourceManagement;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Interfaces.Configuration;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.Interfaces.Network;
|
||||
using Robust.Shared.Interfaces.Timing;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Robust.Client.GameStates
|
||||
{
|
||||
/// <summary>
|
||||
/// A network entity report that lists all entities as they are updated through game states.
|
||||
/// https://developer.valvesoftware.com/wiki/Networking_Entities#cl_entityreport
|
||||
/// </summary>
|
||||
class NetEntityOverlay : Overlay
|
||||
{
|
||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||
[Dependency] private readonly IClientNetManager _netManager = default!;
|
||||
[Dependency] private readonly IClientGameStateManager _gameStateManager = default!;
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
[Dependency] private readonly IConfigurationManager _configurationManager = default!;
|
||||
[Dependency] private readonly IEyeManager _eyeManager = default!;
|
||||
|
||||
private const int TrafficHistorySize = 64; // Size of the traffic history bar in game ticks.
|
||||
|
||||
/// <inheritdoc />
|
||||
public override OverlaySpace Space => OverlaySpace.ScreenSpace;
|
||||
|
||||
private readonly Font _font;
|
||||
private readonly int _lineHeight;
|
||||
private readonly List<NetEntity> _netEnts = new();
|
||||
|
||||
public NetEntityOverlay() : base(nameof(NetEntityOverlay))
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
var cache = IoCManager.Resolve<IResourceCache>();
|
||||
_font = new VectorFont(cache.GetResource<FontResource>("/Fonts/NotoSans/NotoSans-Regular.ttf"), 10);
|
||||
_lineHeight = _font.GetLineHeight(1);
|
||||
|
||||
_gameStateManager.GameStateApplied += HandleGameStateApplied;
|
||||
}
|
||||
|
||||
private void HandleGameStateApplied(GameStateAppliedArgs args)
|
||||
{
|
||||
if(_gameTiming.InPrediction) // we only care about real server states.
|
||||
return;
|
||||
|
||||
// Shift traffic history down one
|
||||
for (var i = 0; i < _netEnts.Count; i++)
|
||||
{
|
||||
var traffic = _netEnts[i].Traffic;
|
||||
for (int j = 1; j < TrafficHistorySize; j++)
|
||||
{
|
||||
traffic[j - 1] = traffic[j];
|
||||
}
|
||||
|
||||
traffic[^1] = 0;
|
||||
}
|
||||
|
||||
var gameState = args.AppliedState;
|
||||
|
||||
if(gameState.EntityStates is not null)
|
||||
{
|
||||
// Loop over every entity that gets updated this state and record the traffic
|
||||
foreach (var entityState in gameState.EntityStates)
|
||||
{
|
||||
var newEnt = true;
|
||||
for(var i=0;i<_netEnts.Count;i++)
|
||||
{
|
||||
var netEnt = _netEnts[i];
|
||||
|
||||
if (netEnt.Id != entityState.Uid)
|
||||
continue;
|
||||
|
||||
//TODO: calculate size of state and record it here.
|
||||
netEnt.Traffic[^1] = 1;
|
||||
netEnt.LastUpdate = gameState.ToSequence;
|
||||
newEnt = false;
|
||||
_netEnts[i] = netEnt; // copy struct back
|
||||
break;
|
||||
}
|
||||
|
||||
if (!newEnt)
|
||||
continue;
|
||||
|
||||
var newNetEnt = new NetEntity(entityState.Uid);
|
||||
newNetEnt.Traffic[^1] = 1;
|
||||
newNetEnt.LastUpdate = gameState.ToSequence;
|
||||
_netEnts.Add(newNetEnt);
|
||||
}
|
||||
}
|
||||
|
||||
bool pvsEnabled = _configurationManager.GetCVar<bool>("net.pvs");
|
||||
float pvsSize = _configurationManager.GetCVar<float>("net.maxupdaterange");
|
||||
var pvsCenter = _eyeManager.CurrentEye.Position;
|
||||
Box2 pvsBox = Box2.CenteredAround(pvsCenter.Position, new Vector2(pvsSize*2, pvsSize*2));
|
||||
|
||||
int timeout = _gameTiming.TickRate * 3;
|
||||
for (int i = 0; i < _netEnts.Count; i++)
|
||||
{
|
||||
var netEnt = _netEnts[i];
|
||||
|
||||
if(_entityManager.EntityExists(netEnt.Id))
|
||||
{
|
||||
//TODO: Whoever is working on PVS remake, change the InPVS detection.
|
||||
var position = _entityManager.GetEntity(netEnt.Id).Transform.MapPosition;
|
||||
netEnt.InPVS = !pvsEnabled || (pvsBox.Contains(position.Position) && position.MapId == pvsCenter.MapId);
|
||||
_netEnts[i] = netEnt; // copy struct back
|
||||
continue;
|
||||
}
|
||||
|
||||
netEnt.Exists = false;
|
||||
if (netEnt.LastUpdate.Value + timeout < _gameTiming.LastRealTick.Value)
|
||||
{
|
||||
_netEnts.RemoveAt(i);
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
|
||||
_netEnts[i] = netEnt; // copy struct back
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Draw(DrawingHandleBase handle, OverlaySpace currentSpace)
|
||||
{
|
||||
if (!_netManager.IsConnected)
|
||||
return;
|
||||
|
||||
// remember, 0,0 is top left of ui with +X right and +Y down
|
||||
var screenHandle = (DrawingHandleScreen)handle;
|
||||
|
||||
for (int i = 0; i < _netEnts.Count; i++)
|
||||
{
|
||||
var netEnt = _netEnts[i];
|
||||
|
||||
var xPos = 100;
|
||||
var yPos = 10 + _lineHeight * i;
|
||||
var name = $"({netEnt.Id}) {_entityManager.GetEntity(netEnt.Id).Prototype?.ID}";
|
||||
var color = CalcTextColor(ref netEnt);
|
||||
DrawString(screenHandle, _font, new Vector2(xPos + (TrafficHistorySize + 4), yPos), name, color);
|
||||
DrawTrafficBox(screenHandle, ref netEnt, xPos, yPos);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawTrafficBox(DrawingHandleScreen handle, ref NetEntity netEntity, int x, int y)
|
||||
{
|
||||
handle.DrawRect(UIBox2.FromDimensions(x+1, y, TrafficHistorySize + 1, _lineHeight), new Color(32, 32, 32, 128));
|
||||
handle.DrawRect(UIBox2.FromDimensions(x, y, TrafficHistorySize + 2, _lineHeight), Color.Gray.WithAlpha(0.15f), false);
|
||||
|
||||
var traffic = netEntity.Traffic;
|
||||
|
||||
//TODO: Local peak size, actually scale the peaks
|
||||
for (int i = 0; i < TrafficHistorySize; i++)
|
||||
{
|
||||
if(traffic[i] == 0)
|
||||
continue;
|
||||
|
||||
var xPos = x + 1 + i;
|
||||
var yPosA = y + 1;
|
||||
var yPosB = yPosA + _lineHeight - 1;
|
||||
handle.DrawLine(new Vector2(xPos, yPosA), new Vector2(xPos, yPosB), Color.Green);
|
||||
}
|
||||
}
|
||||
|
||||
private Color CalcTextColor(ref NetEntity ent)
|
||||
{
|
||||
if(!ent.Exists)
|
||||
return Color.Gray; // Entity is deleted, will be removed from list soon.
|
||||
|
||||
if(!ent.InPVS)
|
||||
return Color.Red; // Entity still exists outside PVS, but not updated anymore.
|
||||
|
||||
if(_gameTiming.LastRealTick < ent.LastUpdate + _gameTiming.TickRate)
|
||||
return Color.Blue; //Entity in PVS generating ongoing traffic.
|
||||
|
||||
return Color.Green; // Entity in PVS, but not updated recently.
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
_gameStateManager.GameStateApplied -= HandleGameStateApplied;
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
private static void DrawString(DrawingHandleScreen handle, Font font, Vector2 pos, string str, Color textColor)
|
||||
{
|
||||
var baseLine = new Vector2(pos.X, font.GetAscent(1) + pos.Y);
|
||||
|
||||
foreach (var chr in str)
|
||||
{
|
||||
var advance = font.DrawChar(handle, chr, baseLine, 1, textColor);
|
||||
baseLine += new Vector2(advance, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private struct NetEntity
|
||||
{
|
||||
public GameTick LastUpdate;
|
||||
public readonly EntityUid Id;
|
||||
public readonly int[] Traffic;
|
||||
public bool Exists;
|
||||
public bool InPVS;
|
||||
|
||||
public NetEntity(EntityUid id)
|
||||
{
|
||||
LastUpdate = GameTick.Zero;
|
||||
Id = id;
|
||||
Traffic = new int[TrafficHistorySize];
|
||||
Exists = true;
|
||||
InPVS = true;
|
||||
}
|
||||
}
|
||||
|
||||
private class NetEntityReportCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "net_entityreport";
|
||||
public string Help => "net_entityreport <0|1>";
|
||||
public string Description => "Toggles the net entity report panel.";
|
||||
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (args.Length != 1)
|
||||
{
|
||||
shell.WriteLine("Invalid argument amount. Expected 2 arguments.", Color.Red);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!byte.TryParse(args[0], out var iValue))
|
||||
{
|
||||
shell.WriteLine("Invalid argument: Needs to be 0 or 1.", Color.Red);
|
||||
return;
|
||||
}
|
||||
|
||||
var bValue = iValue > 0;
|
||||
var overlayMan = IoCManager.Resolve<IOverlayManager>();
|
||||
|
||||
if(bValue && !overlayMan.HasOverlay(nameof(NetEntityOverlay)))
|
||||
{
|
||||
overlayMan.AddOverlay(new NetEntityOverlay());
|
||||
shell.WriteLine("Enabled network entity report overlay.");
|
||||
}
|
||||
else if(!bValue && overlayMan.HasOverlay(nameof(NetEntityOverlay)))
|
||||
{
|
||||
overlayMan.RemoveOverlay(nameof(NetEntityOverlay));
|
||||
shell.WriteLine("Disabled network entity report overlay.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,11 +2,11 @@
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Graphics.Drawing;
|
||||
using Robust.Client.Graphics.Overlays;
|
||||
using Robust.Client.Interfaces.Console;
|
||||
using Robust.Client.Interfaces.GameStates;
|
||||
using Robust.Client.Interfaces.Graphics.Overlays;
|
||||
using Robust.Client.Interfaces.ResourceManagement;
|
||||
using Robust.Client.ResourceManagement;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.Interfaces.Network;
|
||||
using Robust.Shared.Interfaces.Timing;
|
||||
using Robust.Shared.IoC;
|
||||
@@ -172,18 +172,18 @@ namespace Robust.Client.GameStates
|
||||
public string Help => "net_graph <0|1>";
|
||||
public string Description => "Toggles the net statistics pannel.";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (args.Length != 1)
|
||||
{
|
||||
console.AddLine("Invalid argument amount. Expected 2 arguments.", Color.Red);
|
||||
return false;
|
||||
shell.WriteLine("Invalid argument amount. Expected 2 arguments.", Color.Red);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!byte.TryParse(args[0], out var iValue))
|
||||
{
|
||||
console.AddLine("Invalid argument: Needs to be 0 or 1.");
|
||||
return false;
|
||||
shell.WriteLine("Invalid argument: Needs to be 0 or 1.");
|
||||
return;
|
||||
}
|
||||
|
||||
var bValue = iValue > 0;
|
||||
@@ -192,15 +192,13 @@ namespace Robust.Client.GameStates
|
||||
if(bValue && !overlayMan.HasOverlay(nameof(NetGraphOverlay)))
|
||||
{
|
||||
overlayMan.AddOverlay(new NetGraphOverlay());
|
||||
console.AddLine("Enabled network overlay.");
|
||||
shell.WriteLine("Enabled network overlay.");
|
||||
}
|
||||
else if(overlayMan.HasOverlay(nameof(NetGraphOverlay)))
|
||||
{
|
||||
overlayMan.RemoveOverlay(nameof(NetGraphOverlay));
|
||||
console.AddLine("Disabled network overlay.");
|
||||
shell.WriteLine("Disabled network overlay.");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
using Robust.Client.Graphics.Drawing;
|
||||
using Robust.Client.Graphics.Overlays;
|
||||
using Robust.Client.Graphics.Shaders;
|
||||
using Robust.Client.Interfaces.Console;
|
||||
using Robust.Client.Interfaces.Graphics.ClientEye;
|
||||
using Robust.Client.Interfaces.Graphics.Overlays;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.GameObjects.Components;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.Interfaces.Timing;
|
||||
@@ -34,7 +34,7 @@ namespace Robust.Client.GameStates
|
||||
handle.UseShader(_shader);
|
||||
var worldHandle = (DrawingHandleWorld) handle;
|
||||
var viewport = _eyeManager.GetWorldViewport();
|
||||
foreach (var boundingBox in _componentManager.EntityQuery<IPhysicsComponent>())
|
||||
foreach (var boundingBox in _componentManager.EntityQuery<IPhysicsComponent>(true))
|
||||
{
|
||||
// all entities have a TransformComponent
|
||||
var transform = ((IComponent)boundingBox).Owner.Transform;
|
||||
@@ -73,18 +73,18 @@ namespace Robust.Client.GameStates
|
||||
public string Help => "net_draw_interp <0|1>";
|
||||
public string Description => "Toggles the debug drawing of the network interpolation.";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (args.Length != 1)
|
||||
{
|
||||
console.AddLine("Invalid argument amount. Expected 2 arguments.", Color.Red);
|
||||
return false;
|
||||
shell.WriteLine("Invalid argument amount. Expected 2 arguments.", Color.Red);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!byte.TryParse(args[0], out var iValue))
|
||||
{
|
||||
console.AddLine("Invalid argument: Needs to be 0 or 1.");
|
||||
return false;
|
||||
shell.WriteLine("Invalid argument: Needs to be 0 or 1.");
|
||||
return;
|
||||
}
|
||||
|
||||
var bValue = iValue > 0;
|
||||
@@ -93,15 +93,13 @@ namespace Robust.Client.GameStates
|
||||
if (bValue && !overlayMan.HasOverlay(nameof(NetInterpOverlay)))
|
||||
{
|
||||
overlayMan.AddOverlay(new NetInterpOverlay());
|
||||
console.AddLine("Enabled network interp overlay.");
|
||||
shell.WriteLine("Enabled network interp overlay.");
|
||||
}
|
||||
else if (overlayMan.HasOverlay(nameof(NetInterpOverlay)))
|
||||
{
|
||||
overlayMan.RemoveOverlay(nameof(NetInterpOverlay));
|
||||
console.AddLine("Disabled network interp overlay.");
|
||||
shell.WriteLine("Disabled network interp overlay.");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,8 +27,6 @@ namespace Robust.Client.Graphics.Clyde
|
||||
private const string UniProjViewMatrices = "projectionViewMatrices";
|
||||
private const string UniUniformConstants = "uniformConstants";
|
||||
|
||||
private static readonly Color AmbientLightColor = Color.Black;
|
||||
|
||||
private const int BindingIndexProjView = 0;
|
||||
private const int BindingIndexUniformConstants = 1;
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
{
|
||||
// OpenGL ES capabilities.
|
||||
CheckGLCap(ref _hasGLKhrDebug, "khr_debug", (3, 2), "GL_KHR_debug");
|
||||
if (CompareVersion(3, 2, major, minor))
|
||||
if (!CompareVersion(3, 2, major, minor))
|
||||
{
|
||||
// We're ES <3.2, KHR_debug is extension and needs KHR suffixes.
|
||||
_isGLKhrDebugESExtension = true;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Buffers;
|
||||
using OpenToolkit.Graphics.OpenGL4;
|
||||
using Robust.Client.GameObjects;
|
||||
@@ -30,7 +31,11 @@ namespace Robust.Client.Graphics.Clyde
|
||||
// Horizontal width, in pixels, of the shadow maps used to render FOV.
|
||||
// I figured this was more accuracy sensitive than lights so resolution is significantly higher.
|
||||
private const int FovMapSize = 2048;
|
||||
private const int MaxLightsPerScene = 128;
|
||||
|
||||
// The maximum possible amount of lights in the light list.
|
||||
// In the average case, the only cost of increasing this value is memory.
|
||||
// If you are ever in a situation where this value needs to be increased, however, it will also implicitly cost some CPU time to sort the additional lights.
|
||||
private const int LightsToRenderListSize = 2048;
|
||||
|
||||
private ClydeShaderInstance _fovDebugShaderInstance = default!;
|
||||
|
||||
@@ -80,16 +85,18 @@ namespace Robust.Client.Graphics.Clyde
|
||||
|
||||
// For depth calculation of lighting shadows.
|
||||
private RenderTexture _shadowRenderTarget = default!;
|
||||
// Used because otherwise a MaxLightsPerScene change callback getting hit on startup causes interesting issues (read: bugs)
|
||||
private bool _shadowRenderTargetCanInitializeSafely = false;
|
||||
|
||||
// Proxies to textures of the above render targets.
|
||||
private ClydeTexture FovTexture => _fovRenderTarget.Texture;
|
||||
private ClydeTexture ShadowTexture => _shadowRenderTarget.Texture;
|
||||
|
||||
private readonly (PointLightComponent light, Vector2 pos)[] _lightsToRenderList
|
||||
= new (PointLightComponent light, Vector2 pos)[MaxLightsPerScene];
|
||||
private (PointLightComponent light, Vector2 pos, float distanceSquared)[] _lightsToRenderList = new (PointLightComponent light, Vector2 pos, float distanceSquared)[LightsToRenderListSize];
|
||||
|
||||
private unsafe void InitLighting()
|
||||
{
|
||||
// Other...
|
||||
LoadLightingShaders();
|
||||
|
||||
{
|
||||
@@ -160,10 +167,8 @@ namespace Robust.Client.Graphics.Clyde
|
||||
}
|
||||
|
||||
// Shadow FBO.
|
||||
_shadowRenderTarget = CreateRenderTarget((ShadowMapSize, MaxLightsPerScene),
|
||||
new RenderTargetFormatParameters(_hasGLFloatFramebuffers ? RenderTargetColorFormat.RG32F : RenderTargetColorFormat.Rgba8, true),
|
||||
new TextureSampleParameters {WrapMode = TextureWrapMode.Repeat, Filter = true},
|
||||
nameof(_shadowRenderTarget));
|
||||
_shadowRenderTargetCanInitializeSafely = true;
|
||||
MaxLightsPerSceneChanged(_maxLightsPerScene);
|
||||
}
|
||||
|
||||
private void LoadLightingShaders()
|
||||
@@ -334,6 +339,14 @@ namespace Robust.Client.Graphics.Clyde
|
||||
|
||||
DrawFov(viewport, eye);
|
||||
|
||||
if (!_lightManager.DrawLighting)
|
||||
{
|
||||
BindRenderTargetFull(viewport.RenderTarget);
|
||||
GL.Viewport(0, 0, viewport.Size.X, viewport.Size.Y);
|
||||
CheckGlError();
|
||||
return;
|
||||
}
|
||||
|
||||
using (DebugGroup("Draw shadow depth"))
|
||||
{
|
||||
PrepareDepthDraw(RtToLoaded(_shadowRenderTarget));
|
||||
@@ -344,7 +357,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
{
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
var (light, lightPos) = lights[i];
|
||||
var (light, lightPos, _) = lights[i];
|
||||
|
||||
DrawOcclusionDepth(lightPos, ShadowMapSize, light.Radius, i);
|
||||
}
|
||||
@@ -355,7 +368,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
|
||||
BindRenderTargetImmediate(RtToLoaded(viewport.LightRenderTarget));
|
||||
CheckGlError();
|
||||
GLClearColor(Color.FromSrgb(AmbientLightColor));
|
||||
GLClearColor(_lightManager.AmbientLightColor);
|
||||
GL.Clear(ClearBufferMask.ColorBufferBit);
|
||||
CheckGlError();
|
||||
|
||||
@@ -382,7 +395,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
var (component, lightPos) = lights[i];
|
||||
var (component, lightPos, _) = lights[i];
|
||||
|
||||
var transform = component.Owner.Transform;
|
||||
|
||||
@@ -473,25 +486,24 @@ namespace Robust.Client.Graphics.Clyde
|
||||
_lightingReady = true;
|
||||
}
|
||||
|
||||
private ((PointLightComponent light, Vector2 pos)[] lights, int count, Box2 expandedBounds)
|
||||
private ((PointLightComponent light, Vector2 pos, float distanceSquared)[] lights, int count, Box2 expandedBounds)
|
||||
GetLightsToRender(MapId map, in Box2 worldBounds)
|
||||
{
|
||||
// When culling occluders later, we can't just remove any occluders outside the worldBounds.
|
||||
// As they could still affect the shadows of (large) light sources.
|
||||
// We expand the world bounds so that it encompasses the center of every light source.
|
||||
// This should make it so no culled occluder can make a difference.
|
||||
// (if the occluder is in the current lights at all, it's still not between the light and the world bounds).
|
||||
var expandedBounds = worldBounds;
|
||||
|
||||
var renderingTreeSystem = _entitySystemManager.GetEntitySystem<RenderingTreeSystem>();
|
||||
var lightTree = renderingTreeSystem.GetLightTreeForMap(map);
|
||||
|
||||
var state = (this, expandedBounds, count: 0);
|
||||
var state = (this, worldBounds, count: 0);
|
||||
|
||||
lightTree.QueryAabb(ref state, (ref (Clyde clyde, Box2 expandedBounds, int count) state, in PointLightComponent light) =>
|
||||
lightTree.QueryAabb(ref state, (ref (Clyde clyde, Box2 worldBounds, int count) state, in PointLightComponent light) =>
|
||||
{
|
||||
var transform = light.Owner.Transform;
|
||||
|
||||
if (state.count >= LightsToRenderListSize)
|
||||
{
|
||||
// There are too many lights to fit in the static memory.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!light.Enabled || light.ContainerOccluded)
|
||||
{
|
||||
return true;
|
||||
@@ -501,26 +513,45 @@ namespace Robust.Client.Graphics.Clyde
|
||||
|
||||
var circle = new Circle(lightPos, light.Radius);
|
||||
|
||||
if (!circle.Intersects(state.expandedBounds))
|
||||
// If the light doesn't touch anywhere the camera can see, it doesn't matter.
|
||||
if (!circle.Intersects(state.worldBounds))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
state.clyde._lightsToRenderList[state.count] = (light, lightPos);
|
||||
state.count += 1;
|
||||
|
||||
state.expandedBounds = state.expandedBounds.ExtendToContain(lightPos);
|
||||
|
||||
if (state.count == MaxLightsPerScene)
|
||||
{
|
||||
// TODO: Allow more than MaxLightsPerScene lights.
|
||||
return false;
|
||||
}
|
||||
float distanceSquared = (state.worldBounds.Center - lightPos).LengthSquared;
|
||||
state.clyde._lightsToRenderList[state.count++] = (light, lightPos, distanceSquared);
|
||||
|
||||
return true;
|
||||
}, expandedBounds);
|
||||
}, worldBounds);
|
||||
|
||||
return (_lightsToRenderList, state.count, state.expandedBounds);
|
||||
if (state.count > _maxLightsPerScene)
|
||||
{
|
||||
// There are too many lights to fit in the scene.
|
||||
// This check must occur before occluder expansion, or else bad things happen.
|
||||
// Sort lights by distance.
|
||||
Array.Sort(_lightsToRenderList, 0, state.count, Comparer<(PointLightComponent light, Vector2 pos, float distanceSquared)>.Create((x, y) =>
|
||||
{
|
||||
return x.distanceSquared.CompareTo(y.distanceSquared);
|
||||
}));
|
||||
// Then effectively delete the furthest lights.
|
||||
state.count = _maxLightsPerScene;
|
||||
}
|
||||
|
||||
// When culling occluders later, we can't just remove any occluders outside the worldBounds.
|
||||
// As they could still affect the shadows of (large) light sources.
|
||||
// We expand the world bounds so that it encompasses the center of every light source.
|
||||
// This should make it so no culled occluder can make a difference.
|
||||
// (if the occluder is in the current lights at all, it's still not between the light and the world bounds).
|
||||
var expandedBounds = worldBounds;
|
||||
|
||||
for (var i = 0; i < state.count; i++)
|
||||
{
|
||||
var (_, lightPos, _) = _lightsToRenderList[i];
|
||||
expandedBounds = expandedBounds.ExtendToContain(lightPos);
|
||||
}
|
||||
|
||||
return (_lightsToRenderList, state.count, expandedBounds);
|
||||
}
|
||||
|
||||
private void BlurOntoWalls(Viewport viewport, IEye eye)
|
||||
@@ -959,6 +990,25 @@ namespace Robust.Client.Graphics.Clyde
|
||||
RegenAllLightRts();
|
||||
}
|
||||
|
||||
protected override void MaxLightsPerSceneChanged(int newValue)
|
||||
{
|
||||
_maxLightsPerScene = newValue;
|
||||
|
||||
// This guard is in place because otherwise the shadow FBO is initialized before GL is initialized.
|
||||
if (!_shadowRenderTargetCanInitializeSafely)
|
||||
return;
|
||||
|
||||
if (_shadowRenderTarget != null)
|
||||
{
|
||||
DeleteRenderTexture(_shadowRenderTarget.Handle);
|
||||
}
|
||||
// Shadow FBO.
|
||||
_shadowRenderTarget = CreateRenderTarget((ShadowMapSize, _maxLightsPerScene),
|
||||
new RenderTargetFormatParameters(_hasGLFloatFramebuffers ? RenderTargetColorFormat.RG32F : RenderTargetColorFormat.Rgba8, true),
|
||||
new TextureSampleParameters {WrapMode = TextureWrapMode.Repeat, Filter = true},
|
||||
nameof(_shadowRenderTarget));
|
||||
}
|
||||
|
||||
protected override void SoftShadowsChanged(bool newValue)
|
||||
{
|
||||
_enableSoftShadows = newValue;
|
||||
|
||||
@@ -800,7 +800,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
return;
|
||||
}
|
||||
|
||||
GL.CreateBuffers(1, out uint pbo);
|
||||
GL.GenBuffers(1, out uint pbo);
|
||||
CheckGlError();
|
||||
GL.BindBuffer(BufferTarget.PixelPackBuffer, pbo);
|
||||
CheckGlError();
|
||||
|
||||
@@ -63,6 +63,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
private GLShaderProgram? _currentProgram;
|
||||
|
||||
private int _lightmapDivider = 2;
|
||||
private int _maxLightsPerScene = 128;
|
||||
private bool _enableSoftShadows = true;
|
||||
|
||||
private bool _checkGLErrors;
|
||||
@@ -133,6 +134,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
{
|
||||
base.ReadConfig();
|
||||
_lightmapDivider = _configurationManager.GetCVar(CVars.DisplayLightMapDivider);
|
||||
_maxLightsPerScene = _configurationManager.GetCVar(CVars.DisplayMaxLightsPerScene);
|
||||
_enableSoftShadows = _configurationManager.GetCVar(CVars.DisplaySoftShadows);
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ namespace Robust.Client.Graphics
|
||||
_configurationManager.OnValueChanged(CVars.DisplayVSync, _vSyncChanged, true);
|
||||
_configurationManager.OnValueChanged(CVars.DisplayWindowMode, _windowModeChanged, true);
|
||||
_configurationManager.OnValueChanged(CVars.DisplayLightMapDivider, LightmapDividerChanged, true);
|
||||
_configurationManager.OnValueChanged(CVars.DisplayMaxLightsPerScene, MaxLightsPerSceneChanged, true);
|
||||
_configurationManager.OnValueChanged(CVars.DisplaySoftShadows, SoftShadowsChanged, true);
|
||||
|
||||
return true;
|
||||
@@ -76,6 +77,10 @@ namespace Robust.Client.Graphics
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void MaxLightsPerSceneChanged(int newValue)
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void SoftShadowsChanged(bool newValue)
|
||||
{
|
||||
}
|
||||
|
||||
12
Robust.Client/Graphics/IRsiStateLike.cs
Normal file
12
Robust.Client/Graphics/IRsiStateLike.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
namespace Robust.Client.Graphics
|
||||
{
|
||||
public interface IRsiStateLike : IDirectionalTextureProvider
|
||||
{
|
||||
RSI.State.DirectionType Directions { get; }
|
||||
bool IsAnimated { get; }
|
||||
int AnimationFrameCount { get; }
|
||||
|
||||
float GetDelay(int frame);
|
||||
Texture GetFrame(RSI.State.Direction dir, int frame);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using Robust.Client.Interfaces.Graphics.Lighting;
|
||||
using Robust.Shared.Maths;
|
||||
|
||||
namespace Robust.Client.Graphics.Lighting
|
||||
{
|
||||
@@ -7,5 +8,8 @@ namespace Robust.Client.Graphics.Lighting
|
||||
public bool Enabled { get; set; } = true;
|
||||
public bool DrawShadows { get; set; } = true;
|
||||
public bool DrawHardFov { get; set; } = true;
|
||||
public bool DrawLighting { get; set; } = true;
|
||||
public bool LockConsoleAccess { get; set; } = false;
|
||||
public Color AmbientLightColor { get; set; } = Color.FromSrgb(Color.Black);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Robust.Client.Graphics
|
||||
/// RSIs are folded into a single set of animation timings when loaded.
|
||||
/// This is to simplify animation playback code in-engine.
|
||||
/// </remarks>
|
||||
public sealed class State : IDirectionalTextureProvider
|
||||
public sealed class State : IRsiStateLike
|
||||
{
|
||||
// List of delays for the frame to reach the next frame.
|
||||
private readonly float[] Delays;
|
||||
@@ -80,6 +80,8 @@ namespace Robust.Client.Graphics
|
||||
/// </summary>
|
||||
public bool IsAnimated => DelayCount > 1;
|
||||
|
||||
int IRsiStateLike.AnimationFrameCount => DelayCount;
|
||||
|
||||
public Texture GetFrame(Direction direction, int frame)
|
||||
{
|
||||
return Icons[(int) direction][frame];
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace Robust.Client.Graphics
|
||||
/// Contains a texture used for drawing things.
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public abstract class Texture : IDirectionalTextureProvider
|
||||
public abstract class Texture : IRsiStateLike
|
||||
{
|
||||
/// <summary>
|
||||
/// The width of the texture, in pixels.
|
||||
@@ -85,6 +85,26 @@ namespace Robust.Client.Graphics
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
RSI.State.DirectionType IRsiStateLike.Directions => RSI.State.DirectionType.Dir1;
|
||||
bool IRsiStateLike.IsAnimated => false;
|
||||
int IRsiStateLike.AnimationFrameCount => 0;
|
||||
|
||||
float IRsiStateLike.GetDelay(int frame)
|
||||
{
|
||||
if (frame != 0)
|
||||
throw new IndexOutOfRangeException();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Texture IRsiStateLike.GetFrame(RSI.State.Direction dir, int frame)
|
||||
{
|
||||
if (frame != 0)
|
||||
throw new IndexOutOfRangeException();
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -7,9 +7,9 @@ using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.Interfaces.Console;
|
||||
using Robust.Client.Interfaces.Input;
|
||||
using Robust.Client.Interfaces.UserInterface;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.Input;
|
||||
using Robust.Shared.Input.Binding;
|
||||
using Robust.Shared.Interfaces.Reflection;
|
||||
@@ -812,34 +812,34 @@ namespace Robust.Client.Input
|
||||
public string Description => "Binds an input key to an input command.";
|
||||
public string Help => "bind <KeyName> <BindMode> <InputCommand>";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (args.Length < 3)
|
||||
{
|
||||
console.AddLine("Too few arguments.");
|
||||
return false;
|
||||
shell.WriteLine("Too few arguments.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.Length > 3)
|
||||
{
|
||||
console.AddLine("Too many arguments.");
|
||||
return false;
|
||||
shell.WriteLine("Too many arguments.");
|
||||
return;
|
||||
}
|
||||
|
||||
var keyName = args[0];
|
||||
|
||||
if (!Enum.TryParse(typeof(Key), keyName, true, out var keyIdObj))
|
||||
{
|
||||
console.AddLine($"Key '{keyName}' is unrecognized.");
|
||||
return false;
|
||||
shell.WriteLine($"Key '{keyName}' is unrecognized.");
|
||||
return;
|
||||
}
|
||||
|
||||
var keyId = (Key) keyIdObj!;
|
||||
|
||||
if (!Enum.TryParse(typeof(KeyBindingType), args[1], true, out var keyModeObj))
|
||||
{
|
||||
console.AddLine($"BindMode '{args[1]}' is unrecognized.");
|
||||
return false;
|
||||
shell.WriteLine($"BindMode '{args[1]}' is unrecognized.");
|
||||
return;
|
||||
}
|
||||
|
||||
var keyMode = (KeyBindingType) keyModeObj!;
|
||||
@@ -856,8 +856,6 @@ namespace Robust.Client.Input
|
||||
};
|
||||
|
||||
inputMan.RegisterBinding(registration);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -868,12 +866,10 @@ namespace Robust.Client.Input
|
||||
public string Description => "";
|
||||
public string Help => "";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
IoCManager.Resolve<IInputManager>()
|
||||
.SaveToUserData();
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
using Robust.Shared.Console;
|
||||
|
||||
namespace Robust.Client.Interfaces.Console
|
||||
{
|
||||
public interface IConsoleCommand : ICommand
|
||||
{
|
||||
/// <summary>
|
||||
/// Executes the command
|
||||
/// </summary>
|
||||
/// <returns>Whether or not the command should also be forwarded to the server. True to allow forwarding, false to block.</returns>
|
||||
bool Execute(IDebugConsole console, params string[] args);
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Client.Utility;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Robust.Client.Interfaces.Console
|
||||
{
|
||||
public interface IDebugConsole
|
||||
{
|
||||
IReadOnlyDictionary<string, IConsoleCommand> Commands { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Write a line with a specific color to the console window.
|
||||
/// </summary>
|
||||
void AddLine(string text, Color color);
|
||||
|
||||
void AddLine(string text);
|
||||
|
||||
void AddFormattedLine(FormattedMessage message);
|
||||
|
||||
void Clear();
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,32 @@
|
||||
using Robust.Shared.Maths;
|
||||
|
||||
namespace Robust.Client.Interfaces.Graphics.Lighting
|
||||
{
|
||||
public interface ILightManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Enables/disables the entire light manager.
|
||||
/// </summary>
|
||||
bool Enabled { get; set; }
|
||||
/// <summary>
|
||||
/// Enables/disables shadows, but lights are still functional.
|
||||
/// </summary>
|
||||
bool DrawShadows { get; set; }
|
||||
/// <summary>
|
||||
/// Enables/disables hard FOV.
|
||||
/// </summary>
|
||||
bool DrawHardFov { get; set; }
|
||||
/// <summary>
|
||||
/// Enables/disables everything to do with the lighting buffer, without interfering with hard FOV.
|
||||
/// </summary>
|
||||
bool DrawLighting { get; set; }
|
||||
/// <summary>
|
||||
/// This is useful to prevent players messing with lighting setup when they shouldn't.
|
||||
/// </summary>
|
||||
bool LockConsoleAccess { get; set; }
|
||||
/// <summary>
|
||||
/// Ambient light. This is in linear-light, i.e. when providing a fixed colour, you must use Color.FromSrgb(Color.Black)!
|
||||
/// </summary>
|
||||
Color AmbientLightColor { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Robust.Client.Interfaces.Console;
|
||||
using Robust.Client.Console;
|
||||
using Robust.Shared.Interfaces.Log;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Maths;
|
||||
@@ -12,9 +12,9 @@ namespace Robust.Client.Log
|
||||
/// </summary>
|
||||
class DebugConsoleLogHandler : ILogHandler
|
||||
{
|
||||
readonly IDebugConsole Console;
|
||||
readonly IClientConsoleHost Console;
|
||||
|
||||
public DebugConsoleLogHandler(IDebugConsole console)
|
||||
public DebugConsoleLogHandler(IClientConsoleHost console)
|
||||
{
|
||||
Console = console;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="DiscordRichPresence" Version="1.0.166" />
|
||||
<PackageReference Include="JetBrains.Annotations" Version="2020.1.0" PrivateAssets="All" />
|
||||
<PackageReference Include="nfluidsynth" Version="0.3.0" />
|
||||
<PackageReference Include="nfluidsynth" Version="0.3.1" />
|
||||
<PackageReference Include="NVorbis" Version="0.10.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
<PackageReference Include="NJsonSchema" Version="10.3.1" Condition="'$(Configuration)' == 'Debug'" />
|
||||
|
||||
@@ -33,6 +33,7 @@ namespace Robust.Client.UserInterface
|
||||
}
|
||||
|
||||
public event Action<GUIBoundKeyEventArgs>? OnKeyBindDown;
|
||||
public event Action<GUIBoundKeyEventArgs>? OnKeyBindUp;
|
||||
|
||||
protected internal virtual void KeyBindDown(GUIBoundKeyEventArgs args)
|
||||
{
|
||||
@@ -41,6 +42,7 @@ namespace Robust.Client.UserInterface
|
||||
|
||||
protected internal virtual void KeyBindUp(GUIBoundKeyEventArgs args)
|
||||
{
|
||||
OnKeyBindUp?.Invoke(args);
|
||||
}
|
||||
|
||||
protected internal virtual void MouseMove(GUIMouseMoveEventArgs args)
|
||||
|
||||
62
Robust.Client/UserInterface/Controls/AnimatedTextureRect.cs
Normal file
62
Robust.Client/UserInterface/Controls/AnimatedTextureRect.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Utility;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Robust.Client.UserInterface.Controls
|
||||
{
|
||||
/// <summary>
|
||||
/// A more complex control wrapping <see cref="TextureRect"/> that can do RSI directions and animations.
|
||||
/// </summary>
|
||||
public sealed class AnimatedTextureRect : Control
|
||||
{
|
||||
private IRsiStateLike? _state;
|
||||
private int _curFrame;
|
||||
private float _curFrameTime;
|
||||
|
||||
/// <summary>
|
||||
/// Internal TextureRect used to do actual drawing of the texture.
|
||||
/// You can use this property to change shaders or styling or such.
|
||||
/// </summary>
|
||||
public TextureRect DisplayRect { get; }
|
||||
|
||||
public RSI.State.Direction RsiDirection { get; } = RSI.State.Direction.South;
|
||||
|
||||
public AnimatedTextureRect()
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
|
||||
DisplayRect = new TextureRect();
|
||||
AddChild(DisplayRect);
|
||||
}
|
||||
|
||||
public void SetFromSpriteSpecifier(SpriteSpecifier specifier)
|
||||
{
|
||||
_curFrame = 0;
|
||||
_state = specifier.RsiStateLike();
|
||||
_curFrameTime = _state.GetDelay(0);
|
||||
DisplayRect.Texture = _state.GetFrame(RsiDirection, 0);
|
||||
}
|
||||
|
||||
protected override void FrameUpdate(FrameEventArgs args)
|
||||
{
|
||||
if (!VisibleInTree || _state == null || !_state.IsAnimated)
|
||||
return;
|
||||
|
||||
var oldFrame = _curFrame;
|
||||
|
||||
_curFrameTime -= args.DeltaSeconds;
|
||||
while (_curFrameTime < _state.GetDelay(_curFrame))
|
||||
{
|
||||
_curFrame = (_curFrame + 1) % _state.AnimationFrameCount;
|
||||
_curFrameTime += _state.GetDelay(_curFrame);
|
||||
}
|
||||
|
||||
if (_curFrame != oldFrame)
|
||||
{
|
||||
DisplayRect.Texture = _state.GetFrame(RsiDirection, _curFrame);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -446,8 +446,8 @@ namespace Robust.Client.UserInterface.Controls
|
||||
var (vSepActual, hSepActual) = (Vector2i) (Separations * UIScale);
|
||||
var hSep = _limitDimension == Dimension.Column ? hSepActual : vSepActual;
|
||||
var vSep = _limitDimension == Dimension.Column ? vSepActual : hSepActual;
|
||||
var width = _limitDimension == Dimension.Column ? Width : Height;
|
||||
var height = _limitDimension == Dimension.Column ? Height : Width;
|
||||
var width = _limitDimension == Dimension.Column ? PixelWidth : PixelHeight;
|
||||
var height = _limitDimension == Dimension.Column ? PixelHeight : PixelWidth;
|
||||
|
||||
var stretchMaxX = width - hSep * (cols - 1);
|
||||
var stretchMaxY = height - vSep * (rows - 1);
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.Graphics.Drawing;
|
||||
using Robust.Shared.Maths;
|
||||
|
||||
@@ -20,7 +19,7 @@ namespace Robust.Client.UserInterface.Controls
|
||||
|
||||
protected override void LayoutUpdateOverride()
|
||||
{
|
||||
var contentBox = _getStyleBox()?.GetContentBox(PixelSizeBox) ?? SizeBox;
|
||||
var contentBox = _getStyleBox()?.GetContentBox(PixelSizeBox) ?? PixelSizeBox;
|
||||
|
||||
foreach (var child in Children)
|
||||
{
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace Robust.Client.UserInterface.Controls
|
||||
base.Draw(handle);
|
||||
|
||||
var bg = _getBackground();
|
||||
bg?.Draw(handle, SizeBox);
|
||||
bg?.Draw(handle, PixelSizeBox);
|
||||
|
||||
var fg = _getForeground();
|
||||
if (fg == null)
|
||||
@@ -69,10 +69,10 @@ namespace Robust.Client.UserInterface.Controls
|
||||
return;
|
||||
}
|
||||
var minSize = fg.MinimumSize;
|
||||
var size = Width * GetAsRatio() - minSize.X;
|
||||
var size = PixelWidth * GetAsRatio() - minSize.X;
|
||||
if (size > 0)
|
||||
{
|
||||
fg.Draw(handle, UIBox2.FromDimensions(0, 0, minSize.X + size, Height));
|
||||
fg.Draw(handle, UIBox2.FromDimensions(0, 0, minSize.X + size, PixelHeight));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -85,6 +85,12 @@ namespace Robust.Client.UserInterface.Controls
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void SetValueWithoutEvent(float newValue)
|
||||
{
|
||||
newValue = ClampValue(newValue);
|
||||
_value = newValue;
|
||||
}
|
||||
|
||||
private void _ensureValueClamped()
|
||||
{
|
||||
var newValue = ClampValue(_value);
|
||||
|
||||
@@ -51,7 +51,7 @@ namespace Robust.Client.UserInterface.Controls
|
||||
{
|
||||
var oldHeight = _entry.Height;
|
||||
var oldWidth = _entry.Width;
|
||||
_entry.Update(font, MaxWidth ?? Width, UIScale);
|
||||
_entry.Update(font, (MaxWidth ?? Width) * UIScale, UIScale);
|
||||
if (oldHeight != _entry.Height || MaxWidth != null && _entry.Width != oldWidth)
|
||||
{
|
||||
MinimumSizeChanged();
|
||||
|
||||
@@ -24,6 +24,8 @@ namespace Robust.Client.UserInterface.Controls
|
||||
private StyleBox? _fillStyleBoxOverride;
|
||||
private StyleBox? _grabberStyleBoxOverride;
|
||||
|
||||
public bool Grabbed => _grabbed;
|
||||
|
||||
public StyleBox? ForegroundStyleBoxOverride
|
||||
{
|
||||
get => _foregroundStyleBoxOverride;
|
||||
@@ -97,6 +99,12 @@ namespace Robust.Client.UserInterface.Controls
|
||||
}
|
||||
}
|
||||
|
||||
public override void SetValueWithoutEvent(float newValue)
|
||||
{
|
||||
base.SetValueWithoutEvent(newValue);
|
||||
UpdateValue();
|
||||
}
|
||||
|
||||
private void UpdateValue()
|
||||
{
|
||||
var ratio = GetAsRatio();
|
||||
@@ -131,10 +139,9 @@ namespace Robust.Client.UserInterface.Controls
|
||||
{
|
||||
base.KeyBindUp(args);
|
||||
|
||||
if (args.Function == EngineKeyFunctions.UIClick)
|
||||
{
|
||||
_grabbed = false;
|
||||
}
|
||||
if (args.Function != EngineKeyFunctions.UIClick) return;
|
||||
|
||||
_grabbed = false;
|
||||
}
|
||||
|
||||
protected internal override void MouseMove(GUIMouseMoveEventArgs args)
|
||||
|
||||
@@ -9,6 +9,7 @@ namespace Robust.Client.UserInterface.Controls
|
||||
/// <summary>
|
||||
/// Simple control that draws a single texture using a variety of possible stretching modes.
|
||||
/// </summary>
|
||||
/// <seealso cref="AnimatedTextureRect"/>
|
||||
public class TextureRect : Control
|
||||
{
|
||||
public const string StylePropertyTexture = "texture";
|
||||
@@ -28,8 +29,13 @@ namespace Robust.Client.UserInterface.Controls
|
||||
get => _texture;
|
||||
set
|
||||
{
|
||||
var oldSize = _texture?.Size;
|
||||
_texture = value;
|
||||
MinimumSizeChanged();
|
||||
|
||||
if (value?.Size != oldSize)
|
||||
{
|
||||
MinimumSizeChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ using System.IO;
|
||||
using Newtonsoft.Json;
|
||||
using Robust.Client.Console;
|
||||
using Robust.Client.Graphics.Drawing;
|
||||
using Robust.Client.Interfaces.Console;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Shared.Input;
|
||||
using Robust.Shared.Interfaces.Resources;
|
||||
@@ -15,15 +14,29 @@ using Robust.Shared.Utility;
|
||||
|
||||
namespace Robust.Client.UserInterface.CustomControls
|
||||
{
|
||||
public interface IDebugConsoleView
|
||||
{
|
||||
/// <summary>
|
||||
/// Write a line with a specific color to the console window.
|
||||
/// </summary>
|
||||
void AddLine(string text, Color color);
|
||||
|
||||
void AddLine(string text);
|
||||
|
||||
void AddFormattedLine(FormattedMessage message);
|
||||
|
||||
void Clear();
|
||||
}
|
||||
|
||||
// Quick note on how thread safety works in here:
|
||||
// Messages from other threads are not actually immediately drawn. They're stored in a queue.
|
||||
// Every frame OR the next time a message on the main thread comes in, this queue is drained.
|
||||
// This keeps thread safety while still making it so messages are ordered how they come in.
|
||||
// And also if Update() stops firing due to an exception loop the console will still work.
|
||||
// (At least from the main thread, which is what's throwing the exceptions..)
|
||||
public class DebugConsole : Control, IDebugConsole
|
||||
public class DebugConsole : Control, IDebugConsoleView
|
||||
{
|
||||
private readonly IClientConsole _console;
|
||||
private readonly IClientConsoleHost _consoleHost;
|
||||
private readonly IResourceManager _resourceManager;
|
||||
|
||||
private static readonly ResourcePath HistoryPath = new("/debug_console_history.json");
|
||||
@@ -32,7 +45,6 @@ namespace Robust.Client.UserInterface.CustomControls
|
||||
private readonly OutputPanel Output;
|
||||
private readonly Control MainControl;
|
||||
|
||||
public IReadOnlyDictionary<string, IConsoleCommand> Commands => _console.Commands;
|
||||
private readonly ConcurrentQueue<FormattedMessage> _messageQueue = new();
|
||||
|
||||
private bool _targetVisible;
|
||||
@@ -41,9 +53,9 @@ namespace Robust.Client.UserInterface.CustomControls
|
||||
private readonly List<string> searchResults;
|
||||
private int searchIndex = 0;
|
||||
|
||||
public DebugConsole(IClientConsole console, IResourceManager resMan)
|
||||
public DebugConsole(IClientConsoleHost consoleHost, IResourceManager resMan)
|
||||
{
|
||||
_console = console;
|
||||
_consoleHost = consoleHost;
|
||||
_resourceManager = resMan;
|
||||
|
||||
Visible = false;
|
||||
@@ -82,9 +94,9 @@ namespace Robust.Client.UserInterface.CustomControls
|
||||
CommandBar.OnTextEntered += CommandEntered;
|
||||
CommandBar.OnHistoryChanged += OnHistoryChanged;
|
||||
|
||||
_console.AddString += (_, args) => AddLine(args.Text, args.Color);
|
||||
_console.AddFormatted += (_, args) => AddFormattedLine(args.Message);
|
||||
_console.ClearText += (_, args) => Clear();
|
||||
_consoleHost.AddString += (_, args) => AddLine(args.Text, args.Color);
|
||||
_consoleHost.AddFormatted += (_, args) => AddFormattedLine(args.Message);
|
||||
_consoleHost.ClearText += (_, args) => Clear();
|
||||
|
||||
_loadHistoryFromDisk();
|
||||
|
||||
@@ -141,9 +153,10 @@ namespace Robust.Client.UserInterface.CustomControls
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(args.Text))
|
||||
{
|
||||
_console.ProcessCommand(args.Text);
|
||||
_consoleHost.ExecuteCommand(args.Text);
|
||||
CommandBar.Clear();
|
||||
}
|
||||
|
||||
commandChanged = true;
|
||||
}
|
||||
|
||||
@@ -211,7 +224,7 @@ namespace Robust.Client.UserInterface.CustomControls
|
||||
NextCommand();
|
||||
args.Handle();
|
||||
}
|
||||
else if(args.Function == EngineKeyFunctions.GuiTabNavigatePrev)
|
||||
else if (args.Function == EngineKeyFunctions.GuiTabNavigatePrev)
|
||||
{
|
||||
PrevCommand();
|
||||
args.Handle();
|
||||
@@ -229,7 +242,7 @@ namespace Robust.Client.UserInterface.CustomControls
|
||||
searchResults.Clear();
|
||||
searchIndex = 0;
|
||||
commandChanged = false;
|
||||
foreach (var cmd in Commands)
|
||||
foreach (var cmd in _consoleHost.RegisteredCommands)
|
||||
{
|
||||
if (cmd.Key.StartsWith(CommandBar.Text))
|
||||
{
|
||||
@@ -264,7 +277,7 @@ namespace Robust.Client.UserInterface.CustomControls
|
||||
if (searchResults.Count == 0)
|
||||
return;
|
||||
|
||||
searchIndex = MathHelper.Mod(searchIndex - 1, searchResults.Count);
|
||||
searchIndex = MathHelper.Mod(searchIndex - 1, searchResults.Count);
|
||||
SetInput(searchResults[searchIndex]);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Robust.Client.Interfaces.Console;
|
||||
using Robust.Client.Interfaces.State;
|
||||
using Robust.Client.Interfaces.UserInterface;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.Interfaces.Random;
|
||||
using Robust.Shared.Interfaces.Reflection;
|
||||
using Robust.Shared.IoC;
|
||||
@@ -17,7 +17,7 @@ namespace Robust.Client.UserInterface
|
||||
public string Help => "scene <className>";
|
||||
public string Description => "Immediately changes the UI scene/state.";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var reflection = IoCManager.Resolve<IReflectionManager>();
|
||||
var type = reflection.LooseGetType(args[0]);
|
||||
@@ -25,8 +25,6 @@ namespace Robust.Client.UserInterface
|
||||
var stateMan = IoCManager.Resolve<IStateManager>();
|
||||
|
||||
stateMan.RequestStateChange(type);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace Robust.Client.UserInterface
|
||||
{
|
||||
[Dependency] private readonly IInputManager _inputManager = default!;
|
||||
[Dependency] private readonly IClyde _displayManager = default!;
|
||||
[Dependency] private readonly IClientConsole _console = default!;
|
||||
[Dependency] private readonly IClientConsoleHost _consoleHost = default!;
|
||||
[Dependency] private readonly IResourceManager _resourceManager = default!;
|
||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
@@ -97,7 +97,7 @@ namespace Robust.Client.UserInterface
|
||||
|
||||
_initializeCommon();
|
||||
|
||||
DebugConsole = new DebugConsole(_console, _resourceManager);
|
||||
DebugConsole = new DebugConsole(_consoleHost, _resourceManager);
|
||||
RootControl.AddChild(DebugConsole);
|
||||
|
||||
_debugMonitors = new DebugMonitors(_gameTiming, _playerManager, _eyeManager, _inputManager, _stateManager,
|
||||
|
||||
@@ -4,6 +4,7 @@ using Robust.Client.Graphics;
|
||||
using Robust.Client.Interfaces.ResourceManagement;
|
||||
using Robust.Client.ResourceManagement;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameObjects.Components.Renderable;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Prototypes;
|
||||
@@ -11,66 +12,67 @@ using Robust.Shared.Utility;
|
||||
|
||||
namespace Robust.Client.Utility
|
||||
{
|
||||
/// <summary>
|
||||
/// Helper methods for resolving <see cref="SpriteSpecifier"/>s.
|
||||
/// </summary>
|
||||
public static class SpriteSpecifierExt
|
||||
{
|
||||
public static Texture GetTexture(this SpriteSpecifier.Texture texSpecifier, IResourceCache cache)
|
||||
{
|
||||
return cache
|
||||
.GetResource<TextureResource>(SharedSpriteComponent.TextureRoot / texSpecifier.TexturePath)
|
||||
.Texture;
|
||||
}
|
||||
|
||||
public static RSI.State GetState(this SpriteSpecifier.Rsi rsiSpecifier, IResourceCache cache)
|
||||
{
|
||||
if (cache.TryGetResource<RSIResource>(
|
||||
SharedSpriteComponent.TextureRoot / rsiSpecifier.RsiPath,
|
||||
out var theRsi))
|
||||
{
|
||||
if (theRsi.RSI.TryGetState(rsiSpecifier.RsiState, out var state))
|
||||
{
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
Logger.Error("Failed to load RSI {0}", rsiSpecifier.RsiPath);
|
||||
return SpriteComponent.GetFallbackState(cache);
|
||||
}
|
||||
|
||||
public static Texture Frame0(this SpriteSpecifier specifier)
|
||||
{
|
||||
var resc = IoCManager.Resolve<IResourceCache>();
|
||||
switch (specifier)
|
||||
{
|
||||
case SpriteSpecifier.Texture tex:
|
||||
return resc.GetResource<TextureResource>(SpriteComponent.TextureRoot / tex.TexturePath).Texture;
|
||||
|
||||
case SpriteSpecifier.Rsi rsi:
|
||||
if (resc.TryGetResource<RSIResource>(SpriteComponent.TextureRoot / rsi.RsiPath, out var theRsi))
|
||||
{
|
||||
if (theRsi.RSI.TryGetState(rsi.RsiState, out var state))
|
||||
{
|
||||
return state.Frame0;
|
||||
}
|
||||
}
|
||||
Logger.Error("Failed to load RSI {0}", rsi.RsiPath);
|
||||
return resc.GetFallback<TextureResource>().Texture;
|
||||
case SpriteSpecifier.EntityPrototype prototypeIcon:
|
||||
var protMgr = IoCManager.Resolve<IPrototypeManager>();
|
||||
if (!protMgr.TryIndex<EntityPrototype>(prototypeIcon.EntityPrototypeId, out var prototype))
|
||||
{
|
||||
Logger.Error("Failed to load EntityPrototype for EntityPrototypeId {0}", prototypeIcon.EntityPrototypeId);
|
||||
return resc.GetFallback<TextureResource>().Texture;
|
||||
}
|
||||
return SpriteComponent.GetPrototypeIcon(prototype, resc)?.Default ?? resc.GetFallback<TextureResource>().Texture;
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
return specifier.RsiStateLike().Default;
|
||||
}
|
||||
|
||||
public static IDirectionalTextureProvider DirFrame0(this SpriteSpecifier specifier)
|
||||
{
|
||||
var resc = IoCManager.Resolve<IResourceCache>();
|
||||
return specifier.RsiStateLike();
|
||||
}
|
||||
|
||||
public static IRsiStateLike RsiStateLike(this SpriteSpecifier specifier)
|
||||
{
|
||||
var resC = IoCManager.Resolve<IResourceCache>();
|
||||
switch (specifier)
|
||||
{
|
||||
case SpriteSpecifier.Texture tex:
|
||||
return resc.GetResource<TextureResource>(SpriteComponent.TextureRoot / tex.TexturePath).Texture;
|
||||
return tex.GetTexture(resC);
|
||||
|
||||
case SpriteSpecifier.Rsi rsi:
|
||||
if (resc.TryGetResource<RSIResource>(SpriteComponent.TextureRoot / rsi.RsiPath, out var theRsi))
|
||||
{
|
||||
if (theRsi.RSI.TryGetState(rsi.RsiState, out var state))
|
||||
{
|
||||
return state;
|
||||
}
|
||||
}
|
||||
return resc.GetFallback<TextureResource>().Texture;
|
||||
return rsi.GetState(resC);
|
||||
|
||||
case SpriteSpecifier.EntityPrototype prototypeIcon:
|
||||
var protMgr = IoCManager.Resolve<IPrototypeManager>();
|
||||
if (!protMgr.TryIndex<EntityPrototype>(prototypeIcon.EntityPrototypeId, out var prototype))
|
||||
{
|
||||
Logger.Error("Failed to load PrototypeIcon {0}", prototypeIcon.EntityPrototypeId);
|
||||
return resc.GetFallback<TextureResource>().Texture;
|
||||
return SpriteComponent.GetFallbackState(resC);
|
||||
}
|
||||
return SpriteComponent.GetPrototypeIcon(prototype, resc) ?? resc.GetFallback<TextureResource>().Texture;
|
||||
|
||||
return SpriteComponent.GetPrototypeIcon(prototype, resC);
|
||||
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Utility;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Robust.Client.ViewVariables.Editors
|
||||
{
|
||||
@@ -13,48 +15,32 @@ namespace Robust.Client.ViewVariables.Editors
|
||||
protected override Control MakeUI(object? value)
|
||||
{
|
||||
DebugTools.Assert(value!.GetType().IsEnum);
|
||||
var enumVal = (Enum)value;
|
||||
var enumType = value.GetType();
|
||||
var enumStorageType = enumType.GetEnumUnderlyingType();
|
||||
var enumList = Enum.GetValues(enumType);
|
||||
|
||||
var hBox = new HBoxContainer
|
||||
var optionButton = new OptionButton();
|
||||
foreach (var val in enumList)
|
||||
{
|
||||
CustomMinimumSize = new Vector2(200, 0)
|
||||
};
|
||||
var label = val?.ToString();
|
||||
if (label == null)
|
||||
continue;
|
||||
optionButton.AddItem(label, Convert.ToInt32(val));
|
||||
}
|
||||
|
||||
var lineEdit = new LineEdit
|
||||
{
|
||||
Text = enumVal.ToString(),
|
||||
Editable = !ReadOnly,
|
||||
SizeFlagsHorizontal = Control.SizeFlags.FillExpand
|
||||
};
|
||||
optionButton.SelectId(Convert.ToInt32(value));
|
||||
optionButton.Disabled = ReadOnly;
|
||||
|
||||
if (!ReadOnly)
|
||||
{
|
||||
lineEdit.OnTextEntered += e =>
|
||||
var underlyingType = Enum.GetUnderlyingType(value.GetType());
|
||||
optionButton.OnItemSelected += e =>
|
||||
{
|
||||
var parseSig = new []{typeof(string), typeof(NumberStyles), typeof(CultureInfo), enumStorageType.MakeByRefType()};
|
||||
var parseMethod = enumStorageType.GetMethod("TryParse", parseSig);
|
||||
DebugTools.AssertNotNull(parseMethod);
|
||||
|
||||
var parameters = new object?[] {e.Text, NumberStyles.Integer, CultureInfo.InvariantCulture, null};
|
||||
var parseWorked = (bool)parseMethod!.Invoke(null, parameters)!;
|
||||
|
||||
if (parseWorked) // textbox was the underlying type
|
||||
{
|
||||
DebugTools.AssertNotNull(parameters[3]);
|
||||
ValueChanged(parameters[3]);
|
||||
}
|
||||
else if(Enum.TryParse(enumType, e.Text, true, out var enumValue))
|
||||
{
|
||||
var underlyingVal = Convert.ChangeType(enumValue, enumStorageType);
|
||||
ValueChanged(underlyingVal);
|
||||
}
|
||||
optionButton.SelectId(e.Id);
|
||||
ValueChanged(Convert.ChangeType(e.Id, underlyingType));
|
||||
};
|
||||
}
|
||||
|
||||
hBox.AddChild(lineEdit);
|
||||
return hBox;
|
||||
return optionButton;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Robust.Client.Console;
|
||||
using Robust.Client.Interfaces.GameObjects.Components;
|
||||
using Robust.Client.Interfaces.ResourceManagement;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Client.ViewVariables.Traits;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.Interfaces.Serialization;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Utility;
|
||||
using Robust.Shared.ViewVariables;
|
||||
@@ -38,6 +44,9 @@ namespace Robust.Client.ViewVariables.Instances
|
||||
private TabContainer _tabs = default!;
|
||||
private IEntity _entity = default!;
|
||||
|
||||
private ViewVariablesAddComponentWindow? _addComponentWindow;
|
||||
private bool _addComponentServer;
|
||||
|
||||
private ViewVariablesRemoteSession? _entitySession;
|
||||
|
||||
private ViewVariablesBlobMembers? _membersBlob;
|
||||
@@ -47,6 +56,9 @@ namespace Robust.Client.ViewVariables.Instances
|
||||
private VBoxContainer _serverVariables = default!;
|
||||
private VBoxContainer _serverComponents = default!;
|
||||
|
||||
private Button _clientComponentsAddButton = default!;
|
||||
private Button _serverComponentsAddButton = default!;
|
||||
|
||||
private LineEdit _clientComponentsSearchBar = default!;
|
||||
private LineEdit _serverComponentsSearchBar = default!;
|
||||
|
||||
@@ -135,23 +147,7 @@ namespace Robust.Client.ViewVariables.Instances
|
||||
_tabs.AddChild(_clientComponents);
|
||||
_tabs.SetTabTitle(TabClientComponents, "Client Components");
|
||||
|
||||
_clientComponents.AddChild(_clientComponentsSearchBar = new LineEdit
|
||||
{
|
||||
PlaceHolder = Loc.GetString("Search"),
|
||||
SizeFlagsHorizontal = SizeFlags.FillExpand
|
||||
});
|
||||
|
||||
_clientComponentsSearchBar.OnTextChanged += OnClientComponentsSearchBarChanged;
|
||||
|
||||
// See engine#636 for why the Distinct() call.
|
||||
var componentList = _entity.GetAllComponents().OrderBy(c => c.GetType().ToString());
|
||||
|
||||
foreach (var component in componentList)
|
||||
{
|
||||
var button = new Button {Text = TypeAbbreviation.Abbreviate(component.GetType()), TextAlign = Label.AlignMode.Left};
|
||||
button.OnPressed += args => { ViewVariablesManager.OpenVV(component); };
|
||||
_clientComponents.AddChild(button);
|
||||
}
|
||||
PopulateClientComponents();
|
||||
|
||||
if (!_entity.Uid.IsClientSide())
|
||||
{
|
||||
@@ -163,13 +159,103 @@ namespace Robust.Client.ViewVariables.Instances
|
||||
_tabs.AddChild(_serverComponents);
|
||||
_tabs.SetTabTitle(TabServerComponents, "Server Components");
|
||||
|
||||
_serverComponents.AddChild(_serverComponentsSearchBar = new LineEdit
|
||||
{
|
||||
PlaceHolder = Loc.GetString("Search"),
|
||||
SizeFlagsHorizontal = SizeFlags.FillExpand
|
||||
});
|
||||
PopulateServerComponents(false);
|
||||
}
|
||||
}
|
||||
|
||||
_serverComponentsSearchBar.OnTextChanged += OnServerComponentsSearchBarChanged;
|
||||
private void PopulateClientComponents()
|
||||
{
|
||||
_clientComponents.DisposeAllChildren();
|
||||
|
||||
_clientComponents.AddChild(_clientComponentsSearchBar = new LineEdit
|
||||
{
|
||||
PlaceHolder = Loc.GetString("Search"),
|
||||
SizeFlagsHorizontal = SizeFlags.FillExpand
|
||||
});
|
||||
|
||||
_clientComponents.AddChild(_clientComponentsAddButton = new Button()
|
||||
{
|
||||
Text = Loc.GetString("Add Component"),
|
||||
SizeFlagsHorizontal = SizeFlags.FillExpand
|
||||
});
|
||||
|
||||
_clientComponentsAddButton.OnPressed += OnClientComponentsAddButtonPressed;
|
||||
_clientComponentsSearchBar.OnTextChanged += OnClientComponentsSearchBarChanged;
|
||||
|
||||
var componentList = _entity.GetAllComponents().OrderBy(c => c.GetType().ToString());
|
||||
|
||||
foreach (var component in componentList)
|
||||
{
|
||||
var button = new Button {Text = TypeAbbreviation.Abbreviate(component.GetType()), TextAlign = Label.AlignMode.Left};
|
||||
var removeButton = new TextureButton()
|
||||
{
|
||||
StyleClasses = { SS14Window.StyleClassWindowCloseButton },
|
||||
SizeFlagsHorizontal = SizeFlags.ShrinkEnd
|
||||
};
|
||||
button.OnPressed += _ => ViewVariablesManager.OpenVV(component);
|
||||
removeButton.OnPressed += _ => RemoveClientComponent(component);
|
||||
button.AddChild(removeButton);
|
||||
_clientComponents.AddChild(button);
|
||||
}
|
||||
}
|
||||
|
||||
private async void PopulateServerComponents(bool request = true)
|
||||
{
|
||||
_serverComponents.DisposeAllChildren();
|
||||
|
||||
_serverComponents.AddChild(_serverComponentsSearchBar = new LineEdit
|
||||
{
|
||||
PlaceHolder = Loc.GetString("Search"),
|
||||
SizeFlagsHorizontal = SizeFlags.FillExpand
|
||||
});
|
||||
|
||||
_serverComponents.AddChild(_serverComponentsAddButton = new Button()
|
||||
{
|
||||
Text = Loc.GetString("Add Component"),
|
||||
SizeFlagsHorizontal = SizeFlags.FillExpand
|
||||
});
|
||||
|
||||
_serverComponentsSearchBar.OnTextChanged += OnServerComponentsSearchBarChanged;
|
||||
_serverComponentsAddButton.OnPressed += OnServerComponentsAddButtonPressed;
|
||||
|
||||
if (!request || _entitySession == null) return;
|
||||
|
||||
var componentsBlob = await ViewVariablesManager.RequestData<ViewVariablesBlobEntityComponents>(_entitySession, new ViewVariablesRequestEntityComponents());
|
||||
|
||||
componentsBlob.ComponentTypes.Sort();
|
||||
|
||||
var componentTypes = componentsBlob.ComponentTypes.AsEnumerable();
|
||||
|
||||
if (!string.IsNullOrEmpty(_serverComponentsSearchBar.Text))
|
||||
{
|
||||
componentTypes = componentTypes
|
||||
.Where(t => t.Stringified.Contains(_serverComponentsSearchBar.Text,
|
||||
StringComparison.InvariantCultureIgnoreCase));
|
||||
}
|
||||
|
||||
componentTypes = componentTypes.OrderBy(t => t.Stringified);
|
||||
|
||||
foreach (var componentType in componentTypes)
|
||||
{
|
||||
var button = new Button {Text = componentType.Stringified, TextAlign = Label.AlignMode.Left};
|
||||
var removeButton = new TextureButton()
|
||||
{
|
||||
StyleClasses = { SS14Window.StyleClassWindowCloseButton },
|
||||
SizeFlagsHorizontal = SizeFlags.ShrinkEnd
|
||||
};
|
||||
button.OnPressed += _ =>
|
||||
{
|
||||
ViewVariablesManager.OpenVV(
|
||||
new ViewVariablesComponentSelector(_entity.Uid, componentType.FullName));
|
||||
};
|
||||
removeButton.OnPressed += _ =>
|
||||
{
|
||||
// We send a command to remove the component.
|
||||
IoCManager.Resolve<IClientConsoleHost>().RemoteExecuteCommand(null, $"rmcomp {_entity.Uid} {componentType.ComponentName}");
|
||||
PopulateServerComponents();
|
||||
};
|
||||
button.AddChild(removeButton);
|
||||
_serverComponents.AddChild(button);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,7 +273,7 @@ namespace Robust.Client.ViewVariables.Instances
|
||||
|
||||
foreach (var child in _clientComponents.Children)
|
||||
{
|
||||
if (child is not Button button)
|
||||
if (child is not Button button || child == _clientComponentsAddButton)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -222,7 +308,7 @@ namespace Robust.Client.ViewVariables.Instances
|
||||
|
||||
foreach (var child in _serverComponents.Children)
|
||||
{
|
||||
if (child is not Button button)
|
||||
if (child is not Button button || child == _serverComponentsAddButton)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -253,6 +339,103 @@ namespace Robust.Client.ViewVariables.Instances
|
||||
UpdateServerComponentListVisibility(args.Text);
|
||||
}
|
||||
|
||||
private void OnClientComponentsAddButtonPressed(BaseButton.ButtonEventArgs _)
|
||||
{
|
||||
_addComponentWindow?.Dispose();
|
||||
|
||||
_addComponentWindow = new ViewVariablesAddComponentWindow(GetValidComponentsForAdding(), false);
|
||||
_addComponentWindow.AddComponentButtonPressed += OnTryAddComponent;
|
||||
_addComponentServer = false;
|
||||
|
||||
_addComponentWindow.OpenCentered();
|
||||
}
|
||||
|
||||
private async void OnServerComponentsAddButtonPressed(BaseButton.ButtonEventArgs _)
|
||||
{
|
||||
_addComponentWindow?.Dispose();
|
||||
|
||||
if (_entitySession == null) return;
|
||||
|
||||
_addComponentWindow = new ViewVariablesAddComponentWindow(await GetValidServerComponentsForAdding(), true);
|
||||
_addComponentWindow.AddComponentButtonPressed += OnTryAddComponent;
|
||||
_addComponentServer = true;
|
||||
|
||||
_addComponentWindow.OpenCentered();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an enumeration of components that can *probably* be added to an entity.
|
||||
/// </summary>
|
||||
private IEnumerable<string> GetValidComponentsForAdding()
|
||||
{
|
||||
var componentFactory = IoCManager.Resolve<IComponentFactory>();
|
||||
|
||||
foreach (var type in componentFactory.AllRegisteredTypes)
|
||||
{
|
||||
if (_entity.HasComponent(type))
|
||||
continue;
|
||||
|
||||
yield return (componentFactory.GetRegistration(type).Name);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Requests and returns an enumeration of server-side components that can *probably* be added to an entity.
|
||||
/// </summary>
|
||||
private async Task<IEnumerable<string>> GetValidServerComponentsForAdding()
|
||||
{
|
||||
var blob = (ViewVariablesBlobAllValidComponents)
|
||||
await ViewVariablesManager.RequestData(_entitySession!, new ViewVariablesRequestAllValidComponents());
|
||||
|
||||
return blob.ComponentTypes;
|
||||
}
|
||||
|
||||
private async void OnTryAddComponent(ViewVariablesAddComponentWindow.AddComponentButtonPressedEventArgs eventArgs)
|
||||
{
|
||||
if (_addComponentServer)
|
||||
{
|
||||
// Attempted to add a component to the server entity... We send a command.
|
||||
IoCManager.Resolve<IClientConsoleHost>().RemoteExecuteCommand(null, $"addcomp {_entity.Uid} {eventArgs.Component}");
|
||||
PopulateServerComponents();
|
||||
_addComponentWindow?.Populate(await GetValidServerComponentsForAdding());
|
||||
return;
|
||||
}
|
||||
|
||||
var componentFactory = IoCManager.Resolve<IComponentFactory>();
|
||||
|
||||
if(!componentFactory.TryGetRegistration(eventArgs.Component, out var registration)) return;
|
||||
|
||||
try
|
||||
{
|
||||
var comp = (Component) componentFactory.GetComponent(registration.Type);
|
||||
comp.Owner = _entity;
|
||||
_entityManager.ComponentManager.AddComponent(_entity, comp);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Warning($"Failed to add component!\n{e}");
|
||||
}
|
||||
|
||||
PopulateClientComponents();
|
||||
|
||||
// Update list of components.
|
||||
_addComponentWindow?.Populate(GetValidComponentsForAdding());
|
||||
}
|
||||
|
||||
private void RemoveClientComponent(IComponent component)
|
||||
{
|
||||
try
|
||||
{
|
||||
_entityManager.ComponentManager.RemoveComponent(_entity.Uid, component);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Warning($"Couldn't remove component!\n{e}");
|
||||
}
|
||||
|
||||
PopulateClientComponents();
|
||||
}
|
||||
|
||||
public override async void Initialize(SS14Window window, ViewVariablesBlobMetadata blob, ViewVariablesRemoteSession session)
|
||||
{
|
||||
// TODO: this is pretty poorly implemented right now.
|
||||
@@ -282,6 +465,12 @@ namespace Robust.Client.ViewVariables.Instances
|
||||
|
||||
private async void _tabsOnTabChanged(int tab)
|
||||
{
|
||||
if (tab == TabClientComponents)
|
||||
{
|
||||
// Repopulate client components in case something changed.
|
||||
PopulateClientComponents();
|
||||
}
|
||||
|
||||
if (_serverLoaded || tab != TabServerComponents && tab != TabServerVars)
|
||||
{
|
||||
return;
|
||||
@@ -303,10 +492,10 @@ namespace Robust.Client.ViewVariables.Instances
|
||||
_serverComponents.AddChild(new Label {Text = text});
|
||||
return;
|
||||
}
|
||||
|
||||
_membersBlob = await ViewVariablesManager.RequestData<ViewVariablesBlobMembers>(_entitySession, new ViewVariablesRequestMembers());
|
||||
}
|
||||
|
||||
_membersBlob = await ViewVariablesManager.RequestData<ViewVariablesBlobMembers>(_entitySession, new ViewVariablesRequestMembers());
|
||||
|
||||
var otherStyle = false;
|
||||
var first = true;
|
||||
foreach (var (groupName, groupMembers) in _membersBlob!.MemberGroups)
|
||||
@@ -326,41 +515,7 @@ namespace Robust.Client.ViewVariables.Instances
|
||||
}
|
||||
}
|
||||
|
||||
var componentsBlob = await ViewVariablesManager.RequestData<ViewVariablesBlobEntityComponents>(_entitySession, new ViewVariablesRequestEntityComponents());
|
||||
|
||||
_serverComponents.DisposeAllChildren();
|
||||
|
||||
_serverComponents.AddChild(_serverComponentsSearchBar = new LineEdit
|
||||
{
|
||||
PlaceHolder = Loc.GetString("Search"),
|
||||
SizeFlagsHorizontal = SizeFlags.FillExpand
|
||||
});
|
||||
|
||||
_serverComponentsSearchBar.OnTextChanged += OnServerComponentsSearchBarChanged;
|
||||
|
||||
componentsBlob.ComponentTypes.Sort();
|
||||
|
||||
var componentTypes = componentsBlob.ComponentTypes.AsEnumerable();
|
||||
|
||||
if (!string.IsNullOrEmpty(_serverComponentsSearchBar.Text))
|
||||
{
|
||||
componentTypes = componentTypes
|
||||
.Where(t => t.Stringified.Contains(_serverComponentsSearchBar.Text,
|
||||
StringComparison.InvariantCultureIgnoreCase));
|
||||
}
|
||||
|
||||
componentTypes = componentTypes.OrderBy(t => t.Stringified);
|
||||
|
||||
foreach (var componentType in componentTypes)
|
||||
{
|
||||
var button = new Button {Text = componentType.Stringified, TextAlign = Label.AlignMode.Left};
|
||||
button.OnPressed += args =>
|
||||
{
|
||||
ViewVariablesManager.OpenVV(
|
||||
new ViewVariablesComponentSelector(_entity.Uid, componentType.FullName));
|
||||
};
|
||||
_serverComponents.AddChild(button);
|
||||
}
|
||||
PopulateServerComponents();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<cc:SS14Window xmlns:cc="clr-namespace:Robust.Client.UserInterface.CustomControls"
|
||||
xmlns:c="clr-namespace:Robust.Client.UserInterface.Controls">
|
||||
<c:VBoxContainer SizeFlagsVertical="FillExpand">
|
||||
<c:LineEdit Name="SearchLineEdit" PlaceHolder="Search component..." SizeFlagsHorizontal="FillExpand" />
|
||||
<c:ItemList Name="ComponentItemList" SizeFlagsVertical="FillExpand" SizeFlagsHorizontal="FillExpand" SelectMode="Single" />
|
||||
<c:Button Name="AddButton" Text="Add Component" TextAlign="Center" SizeFlagsHorizontal="FillExpand"/>
|
||||
</c:VBoxContainer>
|
||||
</cc:SS14Window>
|
||||
@@ -0,0 +1,97 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Maths;
|
||||
|
||||
namespace Robust.Client.ViewVariables
|
||||
{
|
||||
[GenerateTypedNameReferences]
|
||||
public partial class ViewVariablesAddComponentWindow : SS14Window
|
||||
{
|
||||
protected override Vector2? CustomSize => (200f, 300f);
|
||||
|
||||
private string? _lastSearch;
|
||||
private string[] _components = Array.Empty<string>();
|
||||
|
||||
public event Action<AddComponentButtonPressedEventArgs>? AddComponentButtonPressed;
|
||||
|
||||
public ViewVariablesAddComponentWindow(IEnumerable<string> components, bool serverside)
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
|
||||
Title = Loc.GetString(serverside ? "Add Component [S]" : "Add Component [C]");
|
||||
|
||||
ComponentItemList.OnItemSelected += _ => RefreshAddButton();
|
||||
ComponentItemList.OnItemDeselected += _ => RefreshAddButton();
|
||||
SearchLineEdit.OnTextChanged += OnSearchTextChanged;
|
||||
AddButton.OnPressed += OnAddButtonPressed;
|
||||
|
||||
Populate(components);
|
||||
}
|
||||
|
||||
private void RefreshAddButton()
|
||||
{
|
||||
AddButton.Disabled = !ComponentItemList.GetSelected().Any();
|
||||
}
|
||||
|
||||
public void Populate(IEnumerable<string> components)
|
||||
{
|
||||
_components = components.ToArray();
|
||||
Array.Sort(_components);
|
||||
Populate(_lastSearch);
|
||||
}
|
||||
|
||||
private void Populate(string? search = null)
|
||||
{
|
||||
_lastSearch = search;
|
||||
ComponentItemList.ClearSelected();
|
||||
ComponentItemList.Clear();
|
||||
AddButton.Disabled = true;
|
||||
|
||||
foreach (var component in _components)
|
||||
{
|
||||
if(!string.IsNullOrEmpty(search) && !component.Contains(search, StringComparison.InvariantCultureIgnoreCase))
|
||||
continue;
|
||||
|
||||
ComponentItemList.AddItem(component);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSearchTextChanged(LineEdit.LineEditEventArgs obj)
|
||||
{
|
||||
Populate(obj.Text);
|
||||
}
|
||||
|
||||
private void OnAddButtonPressed(BaseButton.ButtonEventArgs obj)
|
||||
{
|
||||
var selected = ComponentItemList.GetSelected().ToArray();
|
||||
|
||||
// Nothing to do here!
|
||||
if (selected.Length == 0)
|
||||
return;
|
||||
|
||||
var comp = selected[0];
|
||||
|
||||
// This shouldn't really happen.
|
||||
if (comp.Text == null)
|
||||
return;
|
||||
|
||||
AddComponentButtonPressed?.Invoke(new AddComponentButtonPressedEventArgs(comp.Text));
|
||||
}
|
||||
|
||||
public class AddComponentButtonPressedEventArgs : EventArgs
|
||||
{
|
||||
public string Component { get; }
|
||||
|
||||
public AddComponentButtonPressedEventArgs(string component)
|
||||
{
|
||||
Component = component;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.Interfaces.Console;
|
||||
using Robust.Client.Interfaces.UserInterface;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.Interfaces.Reflection;
|
||||
@@ -20,7 +20,7 @@ namespace Robust.Client.ViewVariables
|
||||
public string Description => "Opens View Variables.";
|
||||
public string Help => "Usage: vv <entity ID|IoC interface name|SIoC interface name>";
|
||||
|
||||
public bool Execute(IDebugConsole console, params string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var vvm = IoCManager.Resolve<IViewVariablesManager>();
|
||||
// If you don't provide an entity ID, it opens the test class.
|
||||
@@ -28,7 +28,7 @@ namespace Robust.Client.ViewVariables
|
||||
if (args.Length == 0)
|
||||
{
|
||||
vvm.OpenVV(new VVTest());
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
var valArg = args[0];
|
||||
@@ -37,7 +37,7 @@ namespace Robust.Client.ViewVariables
|
||||
// Server-side IoC selector.
|
||||
var selector = new ViewVariablesIoCSelector(valArg.Substring(1));
|
||||
vvm.OpenVV(selector);
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (valArg.StartsWith("I"))
|
||||
@@ -46,8 +46,8 @@ namespace Robust.Client.ViewVariables
|
||||
var reflection = IoCManager.Resolve<IReflectionManager>();
|
||||
if (!reflection.TryLooseGetType(valArg, out var type))
|
||||
{
|
||||
console.AddLine("Unable to find that type.");
|
||||
return false;
|
||||
shell.WriteLine("Unable to find that type.");
|
||||
return;
|
||||
}
|
||||
|
||||
object obj;
|
||||
@@ -57,11 +57,11 @@ namespace Robust.Client.ViewVariables
|
||||
}
|
||||
catch (UnregisteredTypeException)
|
||||
{
|
||||
console.AddLine("Unable to find that type.");
|
||||
return false;
|
||||
shell.WriteLine("Unable to find that type.");
|
||||
return;
|
||||
}
|
||||
vvm.OpenVV(obj);
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (valArg.StartsWith("guihover"))
|
||||
@@ -70,30 +70,28 @@ namespace Robust.Client.ViewVariables
|
||||
var obj = IoCManager.Resolve<IUserInterfaceManager>().CurrentlyHovered;
|
||||
if (obj == null)
|
||||
{
|
||||
console.AddLine("Not currently hovering any control.");
|
||||
return false;
|
||||
shell.WriteLine("Not currently hovering any control.");
|
||||
return;
|
||||
}
|
||||
vvm.OpenVV(obj);
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Entity.
|
||||
if (!EntityUid.TryParse(args[0], out var uid))
|
||||
{
|
||||
console.AddLine("Invalid specifier format.");
|
||||
return false;
|
||||
shell.WriteLine("Invalid specifier format.");
|
||||
return;
|
||||
}
|
||||
|
||||
var entityManager = IoCManager.Resolve<IEntityManager>();
|
||||
if (!entityManager.TryGetEntity(uid, out var entity))
|
||||
{
|
||||
console.AddLine("That entity does not exist.");
|
||||
return false;
|
||||
shell.WriteLine("That entity does not exist.");
|
||||
return;
|
||||
}
|
||||
|
||||
vvm.OpenVV(entity);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -6,7 +6,6 @@ using System.Threading;
|
||||
using Prometheus;
|
||||
using Robust.Server.Console;
|
||||
using Robust.Server.Interfaces;
|
||||
using Robust.Server.Interfaces.Console;
|
||||
using Robust.Server.Interfaces.GameObjects;
|
||||
using Robust.Server.Interfaces.GameState;
|
||||
using Robust.Server.Interfaces.Placement;
|
||||
@@ -238,7 +237,6 @@ namespace Robust.Server
|
||||
{
|
||||
netMan.Initialize(true);
|
||||
netMan.StartServer();
|
||||
netMan.RegisterNetMessage<MsgSetTickRate>(MsgSetTickRate.NAME);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -310,7 +308,7 @@ namespace Robust.Server
|
||||
prototypeManager.LoadDirectory(new ResourcePath(@"/Prototypes"));
|
||||
prototypeManager.Resync();
|
||||
|
||||
IoCManager.Resolve<IConsoleShell>().Initialize();
|
||||
IoCManager.Resolve<IServerConsoleHost>().Initialize();
|
||||
_entities.Startup();
|
||||
_scriptHost.Initialize();
|
||||
|
||||
@@ -468,7 +466,6 @@ namespace Robust.Server
|
||||
_time.TickRate = b;
|
||||
|
||||
Logger.InfoS("game", $"Tickrate changed to: {b} on tick {_time.CurTick}");
|
||||
SendTickRateUpdateToClients(b);
|
||||
});
|
||||
|
||||
_time.TickRate = (byte) _config.GetCVar(CVars.NetTickrate);
|
||||
@@ -478,14 +475,6 @@ namespace Robust.Server
|
||||
Logger.InfoS("srv", $"Max players: {MaxPlayers}");
|
||||
}
|
||||
|
||||
private void SendTickRateUpdateToClients(byte newTickRate)
|
||||
{
|
||||
var msg = _network.CreateNetMessage<MsgSetTickRate>();
|
||||
msg.NewTickRate = newTickRate;
|
||||
|
||||
_network.ServerSendToAll(msg);
|
||||
}
|
||||
|
||||
// called right before main loop returns, do all saving/cleanup in here
|
||||
private void Cleanup()
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Server.Interfaces.Console;
|
||||
using Robust.Server.Interfaces.Player;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
@@ -8,17 +8,17 @@ using Robust.Shared.IoC;
|
||||
namespace Robust.Server.Console.Commands
|
||||
{
|
||||
[UsedImplicitly]
|
||||
internal sealed class AddCompCommand : IClientCommand
|
||||
internal sealed class AddCompCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "addcomp";
|
||||
public string Description => "Adds a component to an entity";
|
||||
public string Help => "addcomp <uid> <componentName>";
|
||||
|
||||
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (args.Length != 2)
|
||||
{
|
||||
shell.SendText(player, "Wrong number of arguments");
|
||||
shell.WriteLine("Wrong number of arguments");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -39,16 +39,16 @@ namespace Robust.Server.Console.Commands
|
||||
}
|
||||
|
||||
[UsedImplicitly]
|
||||
internal sealed class RemoveCompCommand : IClientCommand
|
||||
internal sealed class RemoveCompCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "rmcomp";
|
||||
public string Description => "Removes a component from an entity.";
|
||||
public string Help => "rmcomp <uid> <componentName>";
|
||||
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (args.Length != 2)
|
||||
{
|
||||
shell.SendText(player, "Wrong number of arguments");
|
||||
shell.WriteLine("Wrong number of arguments");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
using System;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Server.Interfaces.Console;
|
||||
using Robust.Server.Interfaces.Player;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.Interfaces.Configuration;
|
||||
using Robust.Shared.IoC;
|
||||
|
||||
namespace Robust.Server.Console.Commands
|
||||
{
|
||||
[UsedImplicitly]
|
||||
internal sealed class CVarCommand : SharedCVarCommand, IClientCommand
|
||||
internal sealed class CVarCommand : SharedCVarCommand, IConsoleCommand
|
||||
{
|
||||
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
|
||||
public override void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (args.Length < 1 || args.Length > 2)
|
||||
{
|
||||
shell.SendText(player, "Must provide exactly one or two arguments.");
|
||||
shell.WriteLine("Must provide exactly one or two arguments.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -25,13 +25,13 @@ namespace Robust.Server.Console.Commands
|
||||
if (name == "?")
|
||||
{
|
||||
var cvars = configManager.GetRegisteredCVars();
|
||||
shell.SendText(player, string.Join("\n", cvars));
|
||||
shell.WriteLine(string.Join("\n", cvars));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!configManager.IsCVarRegistered(name))
|
||||
{
|
||||
shell.SendText(player, $"CVar '{name}' is not registered. Use 'cvar ?' to get a list of all registered CVars.");
|
||||
shell.WriteLine($"CVar '{name}' is not registered. Use 'cvar ?' to get a list of all registered CVars.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace Robust.Server.Console.Commands
|
||||
{
|
||||
// Read CVar
|
||||
var value = configManager.GetCVar<object>(name);
|
||||
shell.SendText(player, value.ToString());
|
||||
shell.WriteLine(value.ToString()!);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -53,7 +53,7 @@ namespace Robust.Server.Console.Commands
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
shell.SendText(player, $"Input value is in incorrect format for type {type}");
|
||||
shell.WriteLine($"Input value is in incorrect format for type {type}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
using Robust.Server.Interfaces.Console;
|
||||
using Robust.Server.Interfaces.GameObjects;
|
||||
using Robust.Server.Interfaces.Player;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
|
||||
namespace Robust.Server.Console.Commands
|
||||
{
|
||||
public sealed class DeleteCommand : IClientCommand
|
||||
public sealed class DeleteCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "delete";
|
||||
public string Description => "Deletes the entity with the specified ID.";
|
||||
public string Help => "delete <entity UID>";
|
||||
|
||||
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (args.Length != 1)
|
||||
{
|
||||
shell.SendText(player, "You should provide exactly one argument.");
|
||||
shell.WriteLine("You should provide exactly one argument.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -24,13 +24,13 @@ namespace Robust.Server.Console.Commands
|
||||
|
||||
if (!EntityUid.TryParse(args[0], out var uid))
|
||||
{
|
||||
shell.SendText(player, "Invalid entity UID.");
|
||||
shell.WriteLine("Invalid entity UID.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ent.TryGetEntity(uid, out var entity))
|
||||
{
|
||||
shell.SendText(player, "That entity does not exist.");
|
||||
shell.WriteLine("That entity does not exist.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
using System.Runtime.Loader;
|
||||
using System.Text;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Server.Interfaces.Console;
|
||||
using Robust.Server.Interfaces.Player;
|
||||
using Robust.Shared.Console;
|
||||
|
||||
namespace Robust.Server.Console.Commands
|
||||
{
|
||||
[UsedImplicitly]
|
||||
internal class ListAssembliesCommand : IClientCommand
|
||||
internal class ListAssembliesCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "lsasm";
|
||||
public string Description => "Lists loaded assemblies by load context.";
|
||||
public string Help => Command;
|
||||
|
||||
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
foreach (var context in AssemblyLoadContext.All)
|
||||
@@ -25,7 +25,7 @@ namespace Robust.Server.Console.Commands
|
||||
}
|
||||
}
|
||||
|
||||
shell.SendText(player, sb.ToString());
|
||||
shell.WriteLine(sb.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
using System.Linq;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Robust.Server.Interfaces.Console;
|
||||
using Robust.Server.Interfaces.Player;
|
||||
using Robust.Shared.Console;
|
||||
|
||||
namespace Robust.Server.Console.Commands
|
||||
{
|
||||
public class ListCommands : IClientCommand
|
||||
public class ListCommands : IConsoleCommand
|
||||
{
|
||||
public string Command => "list";
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace Robust.Server.Console.Commands
|
||||
|
||||
public string Help => "Usage: list [filter]";
|
||||
|
||||
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var filter = "";
|
||||
if (args.Length == 1)
|
||||
@@ -24,7 +24,7 @@ namespace Robust.Server.Console.Commands
|
||||
}
|
||||
|
||||
var builder = new StringBuilder("SIDE NAME DESC\n-------------------------\n");
|
||||
foreach (var command in shell.AvailableCommands.Values
|
||||
foreach (var command in shell.ConsoleHost.RegisteredCommands.Values
|
||||
.Where(p => p.Command.Contains(filter))
|
||||
.OrderBy(c => c.Command))
|
||||
{
|
||||
@@ -34,7 +34,7 @@ namespace Robust.Server.Console.Commands
|
||||
}
|
||||
|
||||
var message = builder.ToString().Trim(' ', '\n');
|
||||
shell.SendText(player, message);
|
||||
shell.WriteLine(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
using System;
|
||||
using Robust.Server.Interfaces.Console;
|
||||
using Robust.Server.Interfaces.Player;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.Log;
|
||||
|
||||
namespace Robust.Server.Console.Commands
|
||||
{
|
||||
class LogSetLevelCommand : IClientCommand
|
||||
class LogSetLevelCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "loglevel";
|
||||
public string Description => "Changes the log level for a provided sawmill.";
|
||||
@@ -13,11 +13,11 @@ namespace Robust.Server.Console.Commands
|
||||
+ "\n sawmill: A label prefixing log messages. This is the one you're setting the level for."
|
||||
+ "\n level: The log level. Must match one of the values of the LogLevel enum.";
|
||||
|
||||
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (args.Length != 2)
|
||||
{
|
||||
shell.SendText(player, "Invalid argument amount. Expected 2 arguments.");
|
||||
shell.WriteLine("Invalid argument amount. Expected 2 arguments.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace Robust.Server.Console.Commands
|
||||
{
|
||||
if (!Enum.TryParse<LogLevel>(levelname, out var result))
|
||||
{
|
||||
shell.SendText(player, "Failed to parse 2nd argument. Must be one of the values of the LogLevel enum.");
|
||||
shell.WriteLine("Failed to parse 2nd argument. Must be one of the values of the LogLevel enum.");
|
||||
return;
|
||||
}
|
||||
level = result;
|
||||
@@ -41,7 +41,7 @@ namespace Robust.Server.Console.Commands
|
||||
}
|
||||
}
|
||||
|
||||
class TestLog : IClientCommand
|
||||
class TestLog : IConsoleCommand
|
||||
{
|
||||
public string Command => "testlog";
|
||||
public string Description => "Writes a test log to a sawmill.";
|
||||
@@ -50,11 +50,11 @@ namespace Robust.Server.Console.Commands
|
||||
+ "\n level: The log level. Must match one of the values of the LogLevel enum."
|
||||
+ "\n message: The message to be logged. Wrap this in double quotes if you want to use spaces.";
|
||||
|
||||
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (args.Length != 3)
|
||||
{
|
||||
shell.SendText(player, "Invalid argument amount. Expected exactly 3 arguments.");
|
||||
shell.WriteLine("Invalid argument amount. Expected exactly 3 arguments.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace Robust.Server.Console.Commands
|
||||
var message = args[2]; // yes this doesn't support spaces idgaf.
|
||||
if (!Enum.TryParse<LogLevel>(levelname, out var result))
|
||||
{
|
||||
shell.SendText(player, "Failed to parse 2nd argument. Must be one of the values of the LogLevel enum.");
|
||||
shell.WriteLine("Failed to parse 2nd argument. Must be one of the values of the LogLevel enum.");
|
||||
return;
|
||||
}
|
||||
var level = result;
|
||||
|
||||
@@ -1,25 +1,27 @@
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Robust.Server.Interfaces.Console;
|
||||
using Robust.Server.Interfaces.Maps;
|
||||
using Robust.Server.Interfaces.Player;
|
||||
using Robust.Server.Interfaces.Timing;
|
||||
using Robust.Server.Maps;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.Interfaces.Map;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
|
||||
namespace Robust.Server.Console.Commands
|
||||
{
|
||||
class AddMapCommand : IClientCommand
|
||||
class AddMapCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "addmap";
|
||||
public string Description => "Adds a new empty map to the round. If the mapID already exists, this command does nothing.";
|
||||
public string Help => "addmap <mapID> [initialize]";
|
||||
|
||||
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (args.Length < 1)
|
||||
return;
|
||||
@@ -36,24 +38,24 @@ namespace Robust.Server.Console.Commands
|
||||
{
|
||||
pauseMgr.AddUninitializedMap(mapId);
|
||||
}
|
||||
shell.SendText(player, $"Map with ID {mapId} created.");
|
||||
shell.WriteLine($"Map with ID {mapId} created.");
|
||||
return;
|
||||
}
|
||||
|
||||
shell.SendText(player, $"Map with ID {mapId} already exists!");
|
||||
shell.WriteLine($"Map with ID {mapId} already exists!");
|
||||
}
|
||||
}
|
||||
|
||||
class RemoveMapCommand : IClientCommand
|
||||
class RemoveMapCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "rmmap";
|
||||
public string Description => "Removes a map from the world. You cannot remove nullspace.";
|
||||
public string Help => "rmmap <mapId>";
|
||||
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (args.Length != 1)
|
||||
{
|
||||
shell.SendText(player, "Wrong number of args.");
|
||||
shell.WriteLine("Wrong number of args.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -62,32 +64,32 @@ namespace Robust.Server.Console.Commands
|
||||
|
||||
if (!mapManager.MapExists(mapId))
|
||||
{
|
||||
shell.SendText(player, $"Map {mapId.Value} does not exist.");
|
||||
shell.WriteLine($"Map {mapId.Value} does not exist.");
|
||||
return;
|
||||
}
|
||||
|
||||
mapManager.DeleteMap(mapId);
|
||||
shell.SendText(player, $"Map {mapId.Value} was removed.");
|
||||
shell.WriteLine($"Map {mapId.Value} was removed.");
|
||||
}
|
||||
}
|
||||
|
||||
public class SaveBp : IClientCommand
|
||||
public class SaveBp : IConsoleCommand
|
||||
{
|
||||
public string Command => "savebp";
|
||||
public string Description => "Serializes a grid to disk.";
|
||||
public string Help => "savebp <gridID> <Path>";
|
||||
|
||||
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (args.Length < 2)
|
||||
{
|
||||
shell.SendText(player, "Not enough arguments.");
|
||||
shell.WriteLine("Not enough arguments.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!int.TryParse(args[0], out var intGridId))
|
||||
{
|
||||
shell.SendText(player, "Not a valid grid ID.");
|
||||
shell.WriteLine("Not a valid grid ID.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -98,22 +100,22 @@ namespace Robust.Server.Console.Commands
|
||||
// no saving default grid
|
||||
if (!mapManager.TryGetGrid(gridId, out var grid))
|
||||
{
|
||||
shell.SendText(player, "That grid does not exist.");
|
||||
shell.WriteLine("That grid does not exist.");
|
||||
return;
|
||||
}
|
||||
|
||||
IoCManager.Resolve<IMapLoader>().SaveBlueprint(gridId, args[1]);
|
||||
shell.SendText(player, "Save successful. Look in the user data directory.");
|
||||
shell.WriteLine("Save successful. Look in the user data directory.");
|
||||
}
|
||||
}
|
||||
|
||||
public class LoadBp : IClientCommand
|
||||
public class LoadBp : IConsoleCommand
|
||||
{
|
||||
public string Command => "loadbp";
|
||||
public string Description => "Loads a blueprint from disk into the game.";
|
||||
public string Help => "loadbp <MapID> <Path>";
|
||||
public string Help => "loadbp <MapID> <Path> [storeUids]";
|
||||
|
||||
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (args.Length < 2)
|
||||
{
|
||||
@@ -130,29 +132,35 @@ namespace Robust.Server.Console.Commands
|
||||
// no loading into null space
|
||||
if (mapId == MapId.Nullspace)
|
||||
{
|
||||
shell.SendText(player, "Cannot load into nullspace.");
|
||||
shell.WriteLine("Cannot load into nullspace.");
|
||||
return;
|
||||
}
|
||||
|
||||
var mapManager = IoCManager.Resolve<IMapManager>();
|
||||
if (!mapManager.MapExists(mapId))
|
||||
{
|
||||
shell.SendText(player, "Target map does not exist.");
|
||||
shell.WriteLine("Target map does not exist.");
|
||||
return;
|
||||
}
|
||||
|
||||
var loadOptions = new MapLoadOptions();
|
||||
if (args.Length > 2)
|
||||
{
|
||||
loadOptions.StoreMapUids = bool.Parse(args[2]);
|
||||
}
|
||||
|
||||
var mapLoader = IoCManager.Resolve<IMapLoader>();
|
||||
mapLoader.LoadBlueprint(mapId, args[1]);
|
||||
mapLoader.LoadBlueprint(mapId, args[1], loadOptions);
|
||||
}
|
||||
}
|
||||
|
||||
public class SaveMap : IClientCommand
|
||||
public class SaveMap : IConsoleCommand
|
||||
{
|
||||
public string Command => "savemap";
|
||||
public string Description => "Serializes a map to disk.";
|
||||
public string Help => "savemap <MapID> <Path>";
|
||||
|
||||
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (args.Length < 1)
|
||||
return;
|
||||
@@ -175,13 +183,13 @@ namespace Robust.Server.Console.Commands
|
||||
}
|
||||
}
|
||||
|
||||
public class LoadMap : IClientCommand
|
||||
public class LoadMap : IConsoleCommand
|
||||
{
|
||||
public string Command => "loadmap";
|
||||
public string Description => "Loads a map from disk into the game.";
|
||||
public string Help => "loadmap <MapID> <Path>";
|
||||
|
||||
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (args.Length < 1)
|
||||
return;
|
||||
@@ -194,50 +202,56 @@ namespace Robust.Server.Console.Commands
|
||||
// no loading null space
|
||||
if (mapID == MapId.Nullspace)
|
||||
{
|
||||
shell.SendText(player, "You cannot load into map 0.");
|
||||
shell.WriteLine("You cannot load into map 0.");
|
||||
return;
|
||||
}
|
||||
|
||||
var mapManager = IoCManager.Resolve<IMapManager>();
|
||||
if (mapManager.MapExists(mapID))
|
||||
{
|
||||
shell.SendText(player, $"Map {mapID} already exists.");
|
||||
shell.WriteLine($"Map {mapID} already exists.");
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Parse path
|
||||
var mapPath = "Maps/Demo/DemoMap.yaml";
|
||||
IoCManager.Resolve<IMapLoader>().LoadMap(mapID, mapPath);
|
||||
shell.SendText(player, $"Map {mapID} has been loaded from {mapPath}.");
|
||||
shell.WriteLine($"Map {mapID} has been loaded from {mapPath}.");
|
||||
}
|
||||
}
|
||||
|
||||
class LocationCommand : IClientCommand
|
||||
class LocationCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "loc";
|
||||
public string Description => "Prints the absolute location of the player's entity to console.";
|
||||
public string Help => "loc";
|
||||
|
||||
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if(player?.AttachedEntity == null)
|
||||
var player = shell.Player as IPlayerSession;
|
||||
if (player?.AttachedEntity == null)
|
||||
return;
|
||||
|
||||
var pos = player.AttachedEntity.Transform.Coordinates;
|
||||
var entityManager = IoCManager.Resolve<IEntityManager>();
|
||||
|
||||
shell.SendText(player,
|
||||
$"MapID:{pos.GetMapId(entityManager)} GridID:{pos.GetGridId(entityManager)} X:{pos.X:N2} Y:{pos.Y:N2}");
|
||||
shell.WriteLine($"MapID:{pos.GetMapId(entityManager)} GridID:{pos.GetGridId(entityManager)} X:{pos.X:N2} Y:{pos.Y:N2}");
|
||||
}
|
||||
}
|
||||
|
||||
class PauseMapCommand : IClientCommand
|
||||
class PauseMapCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "pausemap";
|
||||
public string Description => "Pauses a map, pausing all simulation processing on it.";
|
||||
public string Help => "Usage: pausemap <map ID>";
|
||||
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (args.Length != 1)
|
||||
{
|
||||
shell.WriteLine(Loc.GetString("Need to supply a valid MapId"));
|
||||
return;
|
||||
}
|
||||
|
||||
var arg = args[0];
|
||||
var mapId = new MapId(int.Parse(arg, CultureInfo.InvariantCulture));
|
||||
|
||||
@@ -245,20 +259,26 @@ namespace Robust.Server.Console.Commands
|
||||
var mapManager = IoCManager.Resolve<IMapManager>();
|
||||
if (!mapManager.MapExists(mapId))
|
||||
{
|
||||
shell.SendText(player, "That map does not exist.");
|
||||
shell.WriteLine("That map does not exist.");
|
||||
return;
|
||||
}
|
||||
pauseManager.SetMapPaused(mapId, true);
|
||||
}
|
||||
}
|
||||
|
||||
class UnpauseMapCommand : IClientCommand
|
||||
class UnpauseMapCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "unpausemap";
|
||||
public string Description => "unpauses a map, resuming all simulation processing on it.";
|
||||
public string Help => "Usage: unpausemap <map ID>";
|
||||
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (args.Length != 1)
|
||||
{
|
||||
shell.WriteLine(Loc.GetString("Need to supply a valid MapId"));
|
||||
return;
|
||||
}
|
||||
|
||||
var arg = args[0];
|
||||
var mapId = new MapId(int.Parse(arg, CultureInfo.InvariantCulture));
|
||||
|
||||
@@ -266,19 +286,19 @@ namespace Robust.Server.Console.Commands
|
||||
var mapManager = IoCManager.Resolve<IMapManager>();
|
||||
if (!mapManager.MapExists(mapId))
|
||||
{
|
||||
shell.SendText(player, "That map does not exist.");
|
||||
shell.WriteLine("That map does not exist.");
|
||||
return;
|
||||
}
|
||||
pauseManager.SetMapPaused(mapId, false);
|
||||
}
|
||||
}
|
||||
|
||||
class QueryMapPausedCommand : IClientCommand
|
||||
class QueryMapPausedCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "querymappaused";
|
||||
public string Description => "Check whether a map is paused or not.";
|
||||
public string Help => "Usage: querymappaused <map ID>";
|
||||
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var arg = args[0];
|
||||
var mapId = new MapId(int.Parse(arg, CultureInfo.InvariantCulture));
|
||||
@@ -287,24 +307,24 @@ namespace Robust.Server.Console.Commands
|
||||
var mapManager = IoCManager.Resolve<IMapManager>();
|
||||
if (!mapManager.MapExists(mapId))
|
||||
{
|
||||
shell.SendText(player, "That map does not exist.");
|
||||
shell.WriteLine("That map does not exist.");
|
||||
return;
|
||||
}
|
||||
shell.SendText(player, pauseManager.IsMapPaused(mapId).ToString());
|
||||
shell.WriteLine(pauseManager.IsMapPaused(mapId).ToString());
|
||||
}
|
||||
}
|
||||
|
||||
class TpGridCommand : IClientCommand
|
||||
class TpGridCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "tpgrid";
|
||||
public string Description => "Teleports a grid to a new location.";
|
||||
public string Help => "tpgrid <gridId> <X> <Y> [<MapId>]";
|
||||
|
||||
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (args.Length < 3 || args.Length > 4)
|
||||
{
|
||||
shell.SendText(player, "Wrong number of args.");
|
||||
shell.WriteLine("Wrong number of args.");
|
||||
}
|
||||
|
||||
var gridId = new GridId(int.Parse(args[0]));
|
||||
@@ -320,21 +340,21 @@ namespace Robust.Server.Console.Commands
|
||||
grid.ParentMapId = mapId;
|
||||
grid.WorldPosition = new Vector2(xpos, ypos);
|
||||
|
||||
shell.SendText(player, "Grid was teleported.");
|
||||
shell.WriteLine("Grid was teleported.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class RemoveGridCommand : IClientCommand
|
||||
class RemoveGridCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "rmgrid";
|
||||
public string Description => "Removes a grid from a map. You cannot remove the default grid.";
|
||||
public string Help => "rmgrid <gridId>";
|
||||
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (args.Length != 1)
|
||||
{
|
||||
shell.SendText(player, "Wrong number of args.");
|
||||
shell.WriteLine("Wrong number of args.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -343,26 +363,26 @@ namespace Robust.Server.Console.Commands
|
||||
|
||||
if (!mapManager.GridExists(gridId))
|
||||
{
|
||||
shell.SendText(player, $"Grid {gridId.Value} does not exist.");
|
||||
shell.WriteLine($"Grid {gridId.Value} does not exist.");
|
||||
return;
|
||||
}
|
||||
|
||||
mapManager.DeleteGrid(gridId);
|
||||
shell.SendText(player, $"Grid {gridId.Value} was removed.");
|
||||
shell.WriteLine($"Grid {gridId.Value} was removed.");
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class RunMapInitCommand : IClientCommand
|
||||
internal sealed class RunMapInitCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "mapinit";
|
||||
public string Description => "Runs map init on a map";
|
||||
public string Help => "mapinit <mapID>";
|
||||
|
||||
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (args.Length != 1)
|
||||
{
|
||||
shell.SendText(player, "Wrong number of args.");
|
||||
shell.WriteLine("Wrong number of args.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -374,13 +394,13 @@ namespace Robust.Server.Console.Commands
|
||||
|
||||
if (!mapManager.MapExists(mapId))
|
||||
{
|
||||
shell.SendText(player, "Map does not exist!");
|
||||
shell.WriteLine("Map does not exist!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (pauseManager.IsMapInitialized(mapId))
|
||||
{
|
||||
shell.SendText(player, "Map is already initialized!");
|
||||
shell.WriteLine("Map is already initialized!");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -388,13 +408,13 @@ namespace Robust.Server.Console.Commands
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class ListMapsCommand : IClientCommand
|
||||
internal sealed class ListMapsCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "lsmap";
|
||||
public string Description => "Lists maps";
|
||||
public string Help => "lsmap";
|
||||
|
||||
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var mapManager = IoCManager.Resolve<IMapManager>();
|
||||
var pauseManager = IoCManager.Resolve<IPauseManager>();
|
||||
@@ -410,17 +430,17 @@ namespace Robust.Server.Console.Commands
|
||||
mapManager.GetMapEntityId(mapId));
|
||||
}
|
||||
|
||||
shell.SendText(player, msg.ToString());
|
||||
shell.WriteLine(msg.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class ListGridsCommand : IClientCommand
|
||||
internal sealed class ListGridsCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "lsgrid";
|
||||
public string Description => "List grids";
|
||||
public string Help => "lsgrid";
|
||||
|
||||
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var mapManager = IoCManager.Resolve<IMapManager>();
|
||||
|
||||
@@ -432,7 +452,7 @@ namespace Robust.Server.Console.Commands
|
||||
grid.Index, grid.ParentMapId, grid.WorldPosition, grid.GridEntityId);
|
||||
}
|
||||
|
||||
shell.SendText(player, msg.ToString());
|
||||
shell.WriteLine(msg.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Robust.Server.Interfaces.Console;
|
||||
using Robust.Server.Interfaces.Player;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.Interfaces.Map;
|
||||
@@ -14,14 +14,15 @@ using Robust.Shared.Network;
|
||||
|
||||
namespace Robust.Server.Console.Commands
|
||||
{
|
||||
internal class TeleportCommand : IClientCommand
|
||||
internal class TeleportCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "tp";
|
||||
public string Description => "Teleports a player to any location in the round.";
|
||||
public string Help => "tp <x> <y> [<mapID>]";
|
||||
|
||||
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var player = shell.Player as IPlayerSession;
|
||||
if (player?.Status != SessionStatus.InGame || player.AttachedEntity == null)
|
||||
return;
|
||||
|
||||
@@ -58,18 +59,19 @@ namespace Robust.Server.Console.Commands
|
||||
transform.WorldPosition = position;
|
||||
}
|
||||
|
||||
shell.SendText(player, $"Teleported {player} to {mapId}:{posX},{posY}.");
|
||||
shell.WriteLine($"Teleported {player} to {mapId}:{posX},{posY}.");
|
||||
}
|
||||
}
|
||||
|
||||
public class TeleportToPlayerCommand : IClientCommand
|
||||
public class TeleportToPlayerCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "tpto";
|
||||
public string Description => "Teleports the current player to the location of another player.";
|
||||
public string Help => "tpto <username>";
|
||||
|
||||
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var player = shell.Player as IPlayerSession;
|
||||
if (player?.Status != SessionStatus.InGame || player.AttachedEntity == null)
|
||||
return;
|
||||
|
||||
@@ -89,13 +91,13 @@ namespace Robust.Server.Console.Commands
|
||||
}
|
||||
}
|
||||
|
||||
public class ListPlayers : IClientCommand
|
||||
public class ListPlayers : IConsoleCommand
|
||||
{
|
||||
public string Command => "listplayers";
|
||||
public string Description => "Lists all players currently connected";
|
||||
public string Help => "listplayers";
|
||||
|
||||
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
// Player: number of people connected and their byond keys
|
||||
// Admin: read a byond variable which shows their ip, byond version, ckey, attached entity and hardware id
|
||||
@@ -117,29 +119,29 @@ namespace Robust.Server.Console.Commands
|
||||
p.Name));
|
||||
}
|
||||
|
||||
shell.SendText(player, sb.ToString());
|
||||
shell.WriteLine(sb.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
internal class KickCommand : IClientCommand
|
||||
internal class KickCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "kick";
|
||||
public string Description => "Kicks a connected player out of the server, disconnecting them.";
|
||||
public string Help => "kick <PlayerIndex> [<Reason>]";
|
||||
|
||||
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var players = IoCManager.Resolve<IPlayerManager>();
|
||||
if (args.Length < 1)
|
||||
{
|
||||
var player = shell.Player as IPlayerSession;
|
||||
var toKickPlayer = player ?? players.GetAllPlayers().FirstOrDefault();
|
||||
if (toKickPlayer == null)
|
||||
{
|
||||
shell.SendText(player, "You need to provide a player to kick.");
|
||||
shell.WriteLine("You need to provide a player to kick.");
|
||||
return;
|
||||
}
|
||||
shell.SendText(player,
|
||||
$"You need to provide a player to kick. Try running 'kick {toKickPlayer?.Name}' as an example.");
|
||||
shell.WriteLine($"You need to provide a player to kick. Try running 'kick {toKickPlayer?.Name}' as an example.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
using Robust.Server.Interfaces.Console;
|
||||
using Robust.Server.Interfaces.GameObjects;
|
||||
using Robust.Server.Interfaces.Player;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.Interfaces.GameObjects.Components;
|
||||
using Robust.Shared.IoC;
|
||||
|
||||
namespace Robust.Server.Console.Commands
|
||||
{
|
||||
public class SpawnCommand : IClientCommand
|
||||
public class SpawnCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "spawn";
|
||||
public string Description => "Spawns an entity with specific type at your feet.";
|
||||
public string Help => "spawn <entity type>";
|
||||
|
||||
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var player = shell.Player as IPlayerSession;
|
||||
var ent = IoCManager.Resolve<IServerEntityManager>();
|
||||
if (player?.AttachedEntity != null)
|
||||
{
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Runtime;
|
||||
using System.Text;
|
||||
using Robust.Server.Interfaces;
|
||||
using Robust.Server.Interfaces.Console;
|
||||
using Robust.Server.Interfaces.Player;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.Interfaces.Configuration;
|
||||
using Robust.Shared.Interfaces.Network;
|
||||
using Robust.Shared.Interfaces.Timing;
|
||||
@@ -13,49 +13,49 @@ using Robust.Shared.Serialization;
|
||||
|
||||
namespace Robust.Server.Console.Commands
|
||||
{
|
||||
class RestartCommand : IClientCommand
|
||||
class RestartCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "restart";
|
||||
public string Description => "Gracefully restarts the server (not just the round).";
|
||||
public string Help => "restart";
|
||||
|
||||
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
IoCManager.Resolve<IBaseServer>().Restart();
|
||||
}
|
||||
}
|
||||
|
||||
class ShutdownCommand : IClientCommand
|
||||
class ShutdownCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "shutdown";
|
||||
public string Description => "Gracefully shuts down the server.";
|
||||
public string Help => "shutdown";
|
||||
|
||||
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
IoCManager.Resolve<IBaseServer>().Shutdown(null);
|
||||
}
|
||||
}
|
||||
|
||||
public class SaveConfig : IClientCommand
|
||||
public class SaveConfig : IConsoleCommand
|
||||
{
|
||||
public string Command => "saveconfig";
|
||||
public string Description => "Saves the server configuration to the config file";
|
||||
public string Help => "saveconfig";
|
||||
|
||||
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
IoCManager.Resolve<IConfigurationManager>().SaveToFile();
|
||||
}
|
||||
}
|
||||
|
||||
class NetworkAuditCommand : IClientCommand
|
||||
class NetworkAuditCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "netaudit";
|
||||
public string Description => "Prints into about NetMsg security.";
|
||||
public string Help => "netaudit";
|
||||
|
||||
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var network = (NetManager) IoCManager.Resolve<INetManager>();
|
||||
|
||||
@@ -71,11 +71,11 @@ namespace Robust.Server.Console.Commands
|
||||
sb.AppendLine($"Type: {msgType.Name.PadRight(16)} Call:{call.Target}");
|
||||
}
|
||||
|
||||
shell.SendText(player, sb.ToString());
|
||||
shell.WriteLine(sb.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
class HelpCommand : IClientCommand
|
||||
class HelpCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "help";
|
||||
|
||||
@@ -84,54 +84,52 @@ namespace Robust.Server.Console.Commands
|
||||
|
||||
public string Help => "Help";
|
||||
|
||||
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
switch (args.Length)
|
||||
{
|
||||
case 0:
|
||||
shell.SendText(player,
|
||||
"To display help for a specific command, write 'help <command>'. To list all available commands, write 'list'.");
|
||||
shell.WriteLine("To display help for a specific command, write 'help <command>'. To list all available commands, write 'list'.");
|
||||
break;
|
||||
|
||||
case 1:
|
||||
var commandName = args[0];
|
||||
if (!shell.AvailableCommands.TryGetValue(commandName, out var cmd))
|
||||
if (!shell.ConsoleHost.RegisteredCommands.TryGetValue(commandName, out var cmd))
|
||||
{
|
||||
shell.SendText(player, $"Unknown command: {commandName}");
|
||||
shell.WriteLine($"Unknown command: {commandName}");
|
||||
return;
|
||||
}
|
||||
|
||||
shell.SendText(player, $"Use: {cmd.Help}\n{cmd.Description}");
|
||||
shell.WriteLine($"Use: {cmd.Help}\n{cmd.Description}");
|
||||
break;
|
||||
|
||||
default:
|
||||
shell.SendText(player, "Invalid amount of arguments.");
|
||||
shell.WriteLine("Invalid amount of arguments.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ShowTimeCommand : IClientCommand
|
||||
class ShowTimeCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "showtime";
|
||||
public string Description => "Shows the server time.";
|
||||
public string Help => "showtime";
|
||||
|
||||
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var timing = IoCManager.Resolve<IGameTiming>();
|
||||
shell.SendText(player,
|
||||
$"Paused: {timing.Paused}, CurTick: {timing.CurTick}, CurTime: {timing.CurTime}, RealTime: {timing.RealTime}");
|
||||
shell.WriteLine($"Paused: {timing.Paused}, CurTick: {timing.CurTick}, CurTime: {timing.CurTime}, RealTime: {timing.RealTime}");
|
||||
}
|
||||
}
|
||||
|
||||
internal class GcCommand : IClientCommand
|
||||
internal class GcCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "gc";
|
||||
public string Description => "Run the GC.";
|
||||
public string Help => "gc [generation]";
|
||||
|
||||
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (args.Length == 0)
|
||||
{
|
||||
@@ -142,12 +140,12 @@ namespace Robust.Server.Console.Commands
|
||||
if(int.TryParse(args[0], out int result))
|
||||
GC.Collect(result);
|
||||
else
|
||||
shell.SendText(player, "Failed to parse argument.");
|
||||
shell.WriteLine("Failed to parse argument.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class GcModeCommand : IClientCommand
|
||||
internal class GcModeCommand : IConsoleCommand
|
||||
{
|
||||
|
||||
public string Command => "gc_mode";
|
||||
@@ -156,16 +154,16 @@ namespace Robust.Server.Console.Commands
|
||||
|
||||
public string Help => "gc_mode [type]";
|
||||
|
||||
public void Execute(IConsoleShell console, IPlayerSession? player, string[] args)
|
||||
public void Execute(IConsoleShell console, string argStr, string[] args)
|
||||
{
|
||||
var prevMode = GCSettings.LatencyMode;
|
||||
if (args.Length == 0)
|
||||
{
|
||||
console.SendText(player,$"current gc latency mode: {(int) prevMode} ({prevMode})");
|
||||
console.SendText(player,"possible modes:");
|
||||
console.WriteLine($"current gc latency mode: {(int) prevMode} ({prevMode})");
|
||||
console.WriteLine("possible modes:");
|
||||
foreach (var mode in (int[]) Enum.GetValues(typeof(GCLatencyMode)))
|
||||
{
|
||||
console.SendText(player,$" {mode}: {Enum.GetName(typeof(GCLatencyMode), mode)}");
|
||||
console.WriteLine($" {mode}: {Enum.GetName(typeof(GCLatencyMode), mode)}");
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -177,13 +175,13 @@ namespace Robust.Server.Console.Commands
|
||||
}
|
||||
else if (!Enum.TryParse(args[0], true, out mode))
|
||||
{
|
||||
console.SendText(player,$"unknown gc latency mode: {args[0]}");
|
||||
console.WriteLine($"unknown gc latency mode: {args[0]}");
|
||||
return;
|
||||
}
|
||||
|
||||
console.SendText(player,$"attempting gc latency mode change: {(int) prevMode} ({prevMode}) -> {(int) mode} ({mode})");
|
||||
console.WriteLine($"attempting gc latency mode change: {(int) prevMode} ({prevMode}) -> {(int) mode} ({mode})");
|
||||
GCSettings.LatencyMode = mode;
|
||||
console.SendText(player,$"resulting gc latency mode: {(int) GCSettings.LatencyMode} ({GCSettings.LatencyMode})");
|
||||
console.WriteLine($"resulting gc latency mode: {(int) GCSettings.LatencyMode} ({GCSettings.LatencyMode})");
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -191,7 +189,7 @@ namespace Robust.Server.Console.Commands
|
||||
|
||||
}
|
||||
|
||||
internal class SerializeStatsCommand : IClientCommand
|
||||
internal class SerializeStatsCommand : IConsoleCommand
|
||||
{
|
||||
|
||||
public string Command => "szr_stats";
|
||||
@@ -200,31 +198,31 @@ namespace Robust.Server.Console.Commands
|
||||
|
||||
public string Help => "szr_stats";
|
||||
|
||||
public void Execute(IConsoleShell console, IPlayerSession? player, string[] args)
|
||||
public void Execute(IConsoleShell console, string argStr, string[] args)
|
||||
{
|
||||
|
||||
console.SendText(player,$"serialized: {RobustSerializer.BytesSerialized} bytes, {RobustSerializer.ObjectsSerialized} objects");
|
||||
console.SendText(player,$"largest serialized: {RobustSerializer.LargestObjectSerializedBytes} bytes, {RobustSerializer.LargestObjectSerializedType} objects");
|
||||
console.SendText(player,$"deserialized: {RobustSerializer.BytesDeserialized} bytes, {RobustSerializer.ObjectsDeserialized} objects");
|
||||
console.SendText(player,$"largest serialized: {RobustSerializer.LargestObjectDeserializedBytes} bytes, {RobustSerializer.LargestObjectDeserializedType} objects");
|
||||
console.WriteLine($"serialized: {RobustSerializer.BytesSerialized} bytes, {RobustSerializer.ObjectsSerialized} objects");
|
||||
console.WriteLine($"largest serialized: {RobustSerializer.LargestObjectSerializedBytes} bytes, {RobustSerializer.LargestObjectSerializedType} objects");
|
||||
console.WriteLine($"deserialized: {RobustSerializer.BytesDeserialized} bytes, {RobustSerializer.ObjectsDeserialized} objects");
|
||||
console.WriteLine($"largest serialized: {RobustSerializer.LargestObjectDeserializedBytes} bytes, {RobustSerializer.LargestObjectDeserializedType} objects");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal sealed class MemCommand : IClientCommand
|
||||
internal sealed class MemCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "mem";
|
||||
public string Description => "prints memory info";
|
||||
public string Help => "mem";
|
||||
|
||||
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
#if !NETCOREAPP
|
||||
shell.SendText(player, "Memory info is only available on .NET Core");
|
||||
#else
|
||||
var info = GC.GetGCMemoryInfo();
|
||||
|
||||
shell.SendText(player, $@"Heap Size: {FormatBytes(info.HeapSizeBytes)} Total Allocated: {FormatBytes(GC.GetTotalMemory(false))}");
|
||||
shell.WriteLine($@"Heap Size: {FormatBytes(info.HeapSizeBytes)} Total Allocated: {FormatBytes(GC.GetTotalMemory(false))}");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -1,179 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Robust.Server.Interfaces.Console;
|
||||
using Robust.Server.Interfaces.Player;
|
||||
using Robust.Shared.Interfaces.Configuration;
|
||||
using Robust.Shared.Interfaces.Log;
|
||||
using Robust.Shared.Interfaces.Network;
|
||||
using Robust.Shared.Interfaces.Reflection;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.IoC.Exceptions;
|
||||
using Robust.Shared.Network.Messages;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Robust.Server.Console
|
||||
{
|
||||
/// <inheritdoc />
|
||||
internal class ConsoleShell : IConsoleShell
|
||||
{
|
||||
private const string SawmillName = "con";
|
||||
|
||||
[Dependency] private readonly IReflectionManager _reflectionManager = default!;
|
||||
[Dependency] private readonly IPlayerManager _players = default!;
|
||||
[Dependency] private readonly IServerNetManager _net = default!;
|
||||
[Dependency] private readonly ISystemConsoleManager _systemConsole = default!;
|
||||
[Dependency] private readonly ILogManager _logMan = default!;
|
||||
[Dependency] private readonly IConGroupController _groupController = default!;
|
||||
|
||||
private readonly Dictionary<string, IClientCommand> _availableCommands =
|
||||
new Dictionary<string, IClientCommand>();
|
||||
|
||||
/// <inheritdoc />
|
||||
public IReadOnlyDictionary<string, IClientCommand> AvailableCommands => _availableCommands;
|
||||
|
||||
private void HandleRegistrationRequest(INetChannel senderConnection)
|
||||
{
|
||||
var netMgr = IoCManager.Resolve<IServerNetManager>();
|
||||
var message = netMgr.CreateNetMessage<MsgConCmdReg>();
|
||||
|
||||
var counter = 0;
|
||||
message.Commands = new MsgConCmdReg.Command[AvailableCommands.Count];
|
||||
foreach (var command in AvailableCommands.Values)
|
||||
{
|
||||
message.Commands[counter++] = new MsgConCmdReg.Command
|
||||
{
|
||||
Name = command.Command,
|
||||
Description = command.Description,
|
||||
Help = command.Help
|
||||
};
|
||||
}
|
||||
|
||||
netMgr.ServerSendMessage(message, senderConnection);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Initialize()
|
||||
{
|
||||
ReloadCommands();
|
||||
|
||||
// setup networking with clients
|
||||
_net.RegisterNetMessage<MsgConCmd>(MsgConCmd.NAME, ProcessCommand);
|
||||
_net.RegisterNetMessage<MsgConCmdAck>(MsgConCmdAck.NAME);
|
||||
_net.RegisterNetMessage<MsgConCmdReg>(MsgConCmdReg.NAME,
|
||||
message => HandleRegistrationRequest(message.MsgChannel));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void ReloadCommands()
|
||||
{
|
||||
// search for all client commands in all assemblies, and register them
|
||||
_availableCommands.Clear();
|
||||
foreach (var type in _reflectionManager.GetAllChildren<IClientCommand>())
|
||||
{
|
||||
var instance = (IClientCommand) Activator.CreateInstance(type, null)!;
|
||||
if (AvailableCommands.TryGetValue(instance.Command, out var duplicate))
|
||||
throw new InvalidImplementationException(instance.GetType(), typeof(IClientCommand),
|
||||
$"Command name already registered: {instance.Command}, previous: {duplicate.GetType()}");
|
||||
|
||||
_availableCommands[instance.Command] = instance;
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessCommand(MsgConCmd message)
|
||||
{
|
||||
var text = message.Text;
|
||||
var sender = message.MsgChannel;
|
||||
var session = _players.GetSessionByChannel(sender);
|
||||
|
||||
_logMan.GetSawmill(SawmillName).Info($"{FormatPlayerString(session)}:{text}");
|
||||
|
||||
ExecuteCommand(session, text);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void ExecuteCommand(string command)
|
||||
{
|
||||
ExecuteCommand(null, command);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void ExecuteCommand(IPlayerSession? session, string command)
|
||||
{
|
||||
try
|
||||
{
|
||||
var args = new List<string>();
|
||||
CommandParsing.ParseArguments(command, args);
|
||||
|
||||
// missing cmdName
|
||||
if (args.Count == 0)
|
||||
return;
|
||||
|
||||
var cmdName = args[0];
|
||||
|
||||
if (_availableCommands.TryGetValue(cmdName, out var conCmd)) // command registered
|
||||
{
|
||||
if (session != null) // remote client
|
||||
{
|
||||
if (_groupController.CanCommand(session, cmdName)) // client has permission
|
||||
{
|
||||
args.RemoveAt(0);
|
||||
conCmd.Execute(this, session, args.ToArray());
|
||||
}
|
||||
else
|
||||
SendText(session, $"Unknown command: '{cmdName}'");
|
||||
}
|
||||
else // system console
|
||||
{
|
||||
args.RemoveAt(0);
|
||||
conCmd.Execute(this, null, args.ToArray());
|
||||
}
|
||||
}
|
||||
else
|
||||
SendText(session, $"Unknown command: '{cmdName}'");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logMan.GetSawmill(SawmillName).Warning($"{FormatPlayerString(session)}: ExecuteError - {command}:\n{e}");
|
||||
SendText(session, $"There was an error while executing the command: {e}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void SendText(IPlayerSession? session, string? text)
|
||||
{
|
||||
if (session != null)
|
||||
SendText(session.ConnectedClient, text);
|
||||
else
|
||||
_systemConsole.Print(text + "\n");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void SendText(INetChannel target, string? text)
|
||||
{
|
||||
var replyMsg = _net.CreateNetMessage<MsgConCmdAck>();
|
||||
replyMsg.Text = text;
|
||||
_net.ServerSendMessage(replyMsg, target);
|
||||
}
|
||||
|
||||
private static string FormatPlayerString(IPlayerSession? session)
|
||||
{
|
||||
return session != null ? $"{session.Name}" : "[HOST]";
|
||||
}
|
||||
|
||||
private class SudoCommand : IClientCommand
|
||||
{
|
||||
public string Command => "sudo";
|
||||
public string Description => "sudo make me a sandwich";
|
||||
public string Help => "sudo";
|
||||
|
||||
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
|
||||
{
|
||||
var command = args[0];
|
||||
var cArgs = args[1..].Select(CommandParsing.Escape);
|
||||
|
||||
shell.ExecuteCommand($"{command} {string.Join(' ', cArgs)}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
15
Robust.Server/Console/IServerConsoleHost.cs
Normal file
15
Robust.Server/Console/IServerConsoleHost.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using Robust.Shared.Console;
|
||||
|
||||
namespace Robust.Server.Console
|
||||
{
|
||||
/// <summary>
|
||||
/// The server console shell that executes commands.
|
||||
/// </summary>
|
||||
public interface IServerConsoleHost : IConsoleHost
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes the ConsoleShell service.
|
||||
/// </summary>
|
||||
void Initialize();
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace Robust.Server.Interfaces.Console
|
||||
namespace Robust.Server.Console
|
||||
{
|
||||
/// <summary>
|
||||
/// Wraps the system console.
|
||||
221
Robust.Server/Console/ServerConsoleHost.cs
Normal file
221
Robust.Server/Console/ServerConsoleHost.cs
Normal file
@@ -0,0 +1,221 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Robust.Server.Interfaces.Player;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.Interfaces.Network;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Network.Messages;
|
||||
using Robust.Shared.Players;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Robust.Server.Console
|
||||
{
|
||||
/// <inheritdoc cref="IServerConsoleHost" />
|
||||
internal class ServerConsoleHost : ConsoleHost, IServerConsoleHost
|
||||
{
|
||||
[Dependency] private readonly IPlayerManager _players = default!;
|
||||
[Dependency] private readonly ISystemConsoleManager _systemConsole = default!;
|
||||
[Dependency] private readonly IConGroupController _groupController = default!;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void ExecuteCommand(ICommonSession? session, string command)
|
||||
{
|
||||
var shell = new ConsoleShell(this, session);
|
||||
ExecuteInShell(shell, command);
|
||||
}
|
||||
|
||||
private void ExecuteInShell(IConsoleShell shell, string command)
|
||||
{
|
||||
try
|
||||
{
|
||||
var args = new List<string>();
|
||||
CommandParsing.ParseArguments(command, args);
|
||||
|
||||
// missing cmdName
|
||||
if (args.Count == 0)
|
||||
return;
|
||||
|
||||
var cmdName = args[0];
|
||||
|
||||
if (AvailableCommands.TryGetValue(cmdName, out var conCmd)) // command registered
|
||||
{
|
||||
if (shell.Player != null) // remote client
|
||||
{
|
||||
if (_groupController.CanCommand((IPlayerSession) shell.Player, cmdName)) // client has permission
|
||||
{
|
||||
args.RemoveAt(0);
|
||||
conCmd.Execute(shell, command, args.ToArray());
|
||||
}
|
||||
else
|
||||
shell.WriteLine($"Unknown command: '{cmdName}'");
|
||||
}
|
||||
else // system console
|
||||
{
|
||||
args.RemoveAt(0);
|
||||
conCmd.Execute(shell, command, args.ToArray());
|
||||
}
|
||||
}
|
||||
else
|
||||
shell.WriteLine($"Unknown command: '{cmdName}'");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LogManager.GetSawmill(SawmillName).Warning($"{FormatPlayerString(shell.Player)}: ExecuteError - {command}:\n{e}");
|
||||
shell.WriteLine($"There was an error while executing the command: {e}");
|
||||
}
|
||||
}
|
||||
|
||||
public override void RemoteExecuteCommand(ICommonSession? session, string command)
|
||||
{
|
||||
//TODO: Server -> Client remote execute, just like how the client forwards the command
|
||||
}
|
||||
|
||||
public override void WriteLine(ICommonSession? session, string text)
|
||||
{
|
||||
if (session is IPlayerSession playerSession)
|
||||
SendText(playerSession, text);
|
||||
else
|
||||
SendText(null as IPlayerSession, text);
|
||||
}
|
||||
|
||||
public override void WriteLine(ICommonSession? session, string text, Color color)
|
||||
{
|
||||
//TODO: Make colors work.
|
||||
WriteLine(session, text);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Initialize()
|
||||
{
|
||||
RegisterCommand("sudo", "sudo make me a sandwich", "sudo <command>", (shell, _, args) =>
|
||||
{
|
||||
var command = args[0];
|
||||
var cArgs = args[1..].Select(CommandParsing.Escape);
|
||||
|
||||
var localShell = shell.ConsoleHost.LocalShell;
|
||||
var sudoShell = new SudoShell(this, localShell, shell);
|
||||
ExecuteInShell(sudoShell, $"{command} {string.Join(' ', cArgs)}");
|
||||
});
|
||||
|
||||
LoadConsoleCommands();
|
||||
|
||||
// setup networking with clients
|
||||
NetManager.RegisterNetMessage<MsgConCmd>(MsgConCmd.NAME, ProcessCommand);
|
||||
NetManager.RegisterNetMessage<MsgConCmdAck>(MsgConCmdAck.NAME);
|
||||
NetManager.RegisterNetMessage<MsgConCmdReg>(MsgConCmdReg.NAME,
|
||||
message => HandleRegistrationRequest(message.MsgChannel));
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
var text = message.Text;
|
||||
var sender = message.MsgChannel;
|
||||
var session = _players.GetSessionByChannel(sender);
|
||||
|
||||
LogManager.GetSawmill(SawmillName).Info($"{FormatPlayerString(session)}:{text}");
|
||||
|
||||
ExecuteCommand(session, text);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a text string to the remote player.
|
||||
/// </summary>
|
||||
/// <param name="session">
|
||||
/// Remote player to send the text message to. If this is null, the text is sent to the local
|
||||
/// console.
|
||||
/// </param>
|
||||
/// <param name="text">Text message to send.</param>
|
||||
private void SendText(IPlayerSession? session, string text)
|
||||
{
|
||||
if (session != null)
|
||||
SendText(session.ConnectedClient, text);
|
||||
else
|
||||
_systemConsole.Print(text + "\n");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a text string to the remote console.
|
||||
/// </summary>
|
||||
/// <param name="target">Net channel to send the text string to.</param>
|
||||
/// <param name="text">Text message to send.</param>
|
||||
private void SendText(INetChannel target, string text)
|
||||
{
|
||||
var replyMsg = NetManager.CreateNetMessage<MsgConCmdAck>();
|
||||
replyMsg.Text = text;
|
||||
NetManager.ServerSendMessage(replyMsg, target);
|
||||
}
|
||||
|
||||
private static string FormatPlayerString(IBaseSession? 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 WriteLine(string text, Color color)
|
||||
{
|
||||
_owner.WriteLine(text, color);
|
||||
_sudoer.WriteLine(text, color);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_owner.Clear();
|
||||
_sudoer.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,7 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Robust.Server.Interfaces;
|
||||
using Robust.Server.Interfaces.Console;
|
||||
using Robust.Shared.Asynchronous;
|
||||
using Robust.Shared.IoC;
|
||||
using Con = System.Console;
|
||||
@@ -11,7 +10,7 @@ namespace Robust.Server.Console
|
||||
{
|
||||
internal sealed class SystemConsoleManager : ISystemConsoleManager, IPostInjectInit, IDisposable
|
||||
{
|
||||
[Dependency] private readonly IConsoleShell _conShell = default!;
|
||||
[Dependency] private readonly IServerConsoleHost _conShell = default!;
|
||||
[Dependency] private readonly ITaskManager _taskManager = default!;
|
||||
[Dependency] private readonly IBaseServer _baseServer = default!;
|
||||
|
||||
@@ -66,7 +65,7 @@ namespace Robust.Server.Console
|
||||
Con.WriteLine("> " + currentBuffer);
|
||||
commandHistory.Add(commandHistory.Count, currentBuffer);
|
||||
historyIndex = commandHistory.Count;
|
||||
ExecuteCommand(currentBuffer);
|
||||
_conShell.ExecuteCommand(currentBuffer);
|
||||
currentBuffer = "";
|
||||
internalCursor = 0;
|
||||
break;
|
||||
@@ -146,11 +145,6 @@ namespace Robust.Server.Console
|
||||
}
|
||||
}
|
||||
|
||||
private void ExecuteCommand(string commandLine)
|
||||
{
|
||||
_conShell.ExecuteCommand(commandLine);
|
||||
}
|
||||
|
||||
public void Print(string text)
|
||||
{
|
||||
Con.Write(text);
|
||||
@@ -181,7 +175,7 @@ namespace Robust.Server.Console
|
||||
|
||||
if (tabCompleteList.Count == 0)
|
||||
{
|
||||
tabCompleteList = _conShell.AvailableCommands.Keys.Where(key => key.StartsWith(currentBuffer)).ToList();
|
||||
tabCompleteList = _conShell.RegisteredCommands.Keys.Where(key => key.StartsWith(currentBuffer)).ToList();
|
||||
if (tabCompleteList.Count == 0)
|
||||
{
|
||||
return String.Empty;
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
using Robust.Server.Interfaces.Console;
|
||||
|
||||
namespace Robust.Server.Console
|
||||
{
|
||||
internal sealed class SystemConsoleManagerDummy : ISystemConsoleManager
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
using Robust.Server.Interfaces.Timing;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameObjects.Components;
|
||||
using Robust.Shared.IoC;
|
||||
|
||||
namespace Robust.Server.GameObjects.Components.Markers
|
||||
namespace Robust.Server.GameObjects.Components
|
||||
{
|
||||
public class IgnorePauseComponent : Component
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(SharedIgnorePauseComponent))]
|
||||
public sealed class IgnorePauseComponent : SharedIgnorePauseComponent
|
||||
{
|
||||
public override string Name => "IgnorePause";
|
||||
|
||||
public override void OnAdd()
|
||||
{
|
||||
base.OnAdd();
|
||||
@@ -162,7 +162,7 @@ namespace Robust.Server.GameObjects.Components.UserInterface
|
||||
_stateDirty = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Switches between closed and open for a specific client.
|
||||
/// </summary>
|
||||
@@ -183,8 +183,8 @@ namespace Robust.Server.GameObjects.Components.UserInterface
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Opens this interface for a specific client.
|
||||
/// </summary>
|
||||
@@ -263,6 +263,7 @@ namespace Robust.Server.GameObjects.Components.UserInterface
|
||||
OnClosed?.Invoke(session);
|
||||
_subscribedSessions.Remove(session);
|
||||
_playerStateOverrides.Remove(session);
|
||||
session.PlayerStatusChanged -= OnSessionOnPlayerStatusChanged;
|
||||
|
||||
if (_subscribedSessions.Count == 0)
|
||||
{
|
||||
|
||||
18
Robust.Server/GameObjects/MapSaveIdComponent.cs
Normal file
18
Robust.Server/GameObjects/MapSaveIdComponent.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Robust.Server.GameObjects
|
||||
{
|
||||
/// <summary>
|
||||
/// Metadata component used to keep consistent UIDs inside map files cross saving.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This component stores the previous map UID of entities from map load.
|
||||
/// This can then be used to re-serialize the entity with the same UID for the merge driver to recognize.
|
||||
/// </remarks>
|
||||
public sealed class MapSaveIdComponent : Component
|
||||
{
|
||||
public override string Name => "MapSaveId";
|
||||
|
||||
public int Uid { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
using Robust.Server.GameObjects.Components.Container;
|
||||
using Robust.Server.GameObjects.Components.Eye;
|
||||
using Robust.Server.GameObjects.Components.Markers;
|
||||
using Robust.Server.GameObjects.Components.UserInterface;
|
||||
using Robust.Server.Interfaces.GameObjects;
|
||||
using Robust.Shared.GameObjects;
|
||||
@@ -61,8 +60,6 @@ namespace Robust.Server.GameObjects
|
||||
Register<ServerUserInterfaceComponent>();
|
||||
RegisterReference<ServerUserInterfaceComponent, SharedUserInterfaceComponent>();
|
||||
|
||||
Register<IgnorePauseComponent>();
|
||||
|
||||
Register<TimerComponent>();
|
||||
|
||||
RegisterIgnore("AnimationPlayer");
|
||||
@@ -73,6 +70,8 @@ namespace Robust.Server.GameObjects
|
||||
Register<DebugExceptionInitializeComponent>();
|
||||
Register<DebugExceptionStartupComponent>();
|
||||
#endif
|
||||
|
||||
Register<MapSaveIdComponent>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -419,7 +419,7 @@ namespace Robust.Server.GameObjects
|
||||
var oldState =
|
||||
(TransformComponent.TransformComponentState) state.ComponentStates[idx];
|
||||
var newState = new TransformComponent.TransformComponentState(Vector2NaN,
|
||||
oldState.Rotation, oldState.ParentID);
|
||||
oldState.Rotation, oldState.ParentID, oldState.NoLocalRotation);
|
||||
state.ComponentStates[idx] = newState;
|
||||
seenMovers.Remove(uid);
|
||||
ClearLastSeenTick(lSeen, uid);
|
||||
@@ -457,7 +457,7 @@ namespace Robust.Server.GameObjects
|
||||
new ComponentState[]
|
||||
{
|
||||
new TransformComponent.TransformComponentState(Vector2NaN, oldState.Rotation,
|
||||
oldState.ParentID)
|
||||
oldState.ParentID, oldState.NoLocalRotation)
|
||||
}));
|
||||
|
||||
seenMovers.Remove(uid);
|
||||
@@ -608,7 +608,7 @@ namespace Robust.Server.GameObjects
|
||||
|
||||
var oldState = (TransformComponent.TransformComponentState) state.ComponentStates[idx];
|
||||
var newState =
|
||||
new TransformComponent.TransformComponentState(Vector2NaN, oldState.Rotation, oldState.ParentID);
|
||||
new TransformComponent.TransformComponentState(Vector2NaN, oldState.Rotation, oldState.ParentID, oldState.NoLocalRotation);
|
||||
state.ComponentStates[idx] = newState;
|
||||
|
||||
|
||||
@@ -661,7 +661,7 @@ namespace Robust.Server.GameObjects
|
||||
var oldState = (TransformComponent.TransformComponentState) state.ComponentStates[idx];
|
||||
var newState =
|
||||
new TransformComponent.TransformComponentState(Vector2NaN, oldState.Rotation,
|
||||
oldState.ParentID);
|
||||
oldState.ParentID, oldState.NoLocalRotation);
|
||||
state.ComponentStates[idx] = newState;
|
||||
seenMovers.Remove(uid);
|
||||
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
using Robust.Server.Interfaces.Player;
|
||||
using Robust.Shared.Console;
|
||||
|
||||
namespace Robust.Server.Interfaces.Console
|
||||
{
|
||||
/// <summary>
|
||||
/// A command, executed from the debug console of a client.
|
||||
/// </summary>
|
||||
public interface IClientCommand : ICommand
|
||||
{
|
||||
/// <summary>
|
||||
/// Executes the client command.
|
||||
/// </summary>
|
||||
/// <param name="shell">The console that executed this command.</param>
|
||||
/// <param name="player">The player that ran this command. This is null if the command was ran by the server console.</param>
|
||||
/// <param name="args">An array of all the parsed arguments.</param>
|
||||
void Execute(IConsoleShell shell, IPlayerSession? player, string[] args);
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Robust.Server.Interfaces.Player;
|
||||
using Robust.Shared.Interfaces.Network;
|
||||
|
||||
namespace Robust.Server.Interfaces.Console
|
||||
{
|
||||
/// <summary>
|
||||
/// The server console shell that executes commands.
|
||||
/// </summary>
|
||||
public interface IConsoleShell
|
||||
{
|
||||
/// <summary>
|
||||
/// A map of (commandName -> ICommand) of every registered command in the shell.
|
||||
/// </summary>
|
||||
IReadOnlyDictionary<string, IClientCommand> AvailableCommands { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the ConsoleShell service.
|
||||
/// </summary>
|
||||
void Initialize();
|
||||
|
||||
/// <summary>
|
||||
/// Scans all loaded assemblies for console commands and registers them. This will NOT sync with connected clients, and
|
||||
/// should only be used during server initialization.
|
||||
/// </summary>
|
||||
void ReloadCommands();
|
||||
|
||||
/// <summary>
|
||||
/// Sends a text string to the remote player.
|
||||
/// </summary>
|
||||
/// <param name="session">Remote player to send the text message to. If this is null, the text is sent to the local console.</param>
|
||||
/// <param name="text">Text message to send.</param>
|
||||
void SendText(IPlayerSession? session, string? text);
|
||||
|
||||
/// <summary>
|
||||
/// Sends a text string to the remote console.
|
||||
/// </summary>
|
||||
/// <param name="target">Net channel to send the text string to.</param>
|
||||
/// <param name="text">Text message to send.</param>
|
||||
void SendText(INetChannel target, string? text);
|
||||
|
||||
/// <summary>
|
||||
/// Execute a command string on the local shell.
|
||||
/// </summary>
|
||||
/// <param name="command">Command string to execute.</param>
|
||||
void ExecuteCommand(string command);
|
||||
|
||||
/// <summary>
|
||||
/// Execute a command string as a player.
|
||||
/// </summary>
|
||||
/// <param name="player">Session of the remote player. If this is null, the command is executed as the local console.</param>
|
||||
/// <param name="command">Command string to execute.</param>
|
||||
void ExecuteCommand(IPlayerSession? player, string command);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using Robust.Server.Maps;
|
||||
using Robust.Shared.Map;
|
||||
using YamlDotNet.RepresentationModel;
|
||||
|
||||
@@ -7,9 +8,11 @@ namespace Robust.Server.Interfaces.Maps
|
||||
public interface IMapLoader
|
||||
{
|
||||
IMapGrid? LoadBlueprint(MapId mapId, string path);
|
||||
IMapGrid? LoadBlueprint(MapId mapId, string path, MapLoadOptions options);
|
||||
void SaveBlueprint(GridId gridId, string yamlPath);
|
||||
|
||||
void LoadMap(MapId mapId, string path);
|
||||
void LoadMap(MapId mapId, string path, MapLoadOptions options);
|
||||
void SaveMap(MapId mapId, string yamlPath);
|
||||
|
||||
event Action<YamlStream, string> LoadedMapData;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Server.GameObjects.Components.Markers;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
|
||||
|
||||
11
Robust.Server/Maps/MapLoadOptions.cs
Normal file
11
Robust.Server/Maps/MapLoadOptions.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
namespace Robust.Server.Maps
|
||||
{
|
||||
public sealed class MapLoadOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// If true, UID components will be created for loaded entities
|
||||
/// to maintain consistency upon subsequent savings.
|
||||
/// </summary>
|
||||
public bool StoreMapUids { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ using Robust.Shared.GameObjects;
|
||||
using System.Globalization;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using System.Linq;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Server.Interfaces.Timing;
|
||||
using Robust.Shared.GameObjects.Components.Map;
|
||||
using Robust.Shared.Interfaces.Serialization;
|
||||
@@ -29,6 +30,8 @@ namespace Robust.Server.Maps
|
||||
/// </summary>
|
||||
public class MapLoader : IMapLoader
|
||||
{
|
||||
private static readonly MapLoadOptions DefaultLoadOptions = new();
|
||||
|
||||
private const int MapFormatVersion = 2;
|
||||
|
||||
[Dependency] private readonly IResourceManager _resMan = default!;
|
||||
@@ -46,7 +49,8 @@ namespace Robust.Server.Maps
|
||||
{
|
||||
var grid = _mapManager.GetGrid(gridId);
|
||||
|
||||
var context = new MapContext(_mapManager, _tileDefinitionManager, _serverEntityManager, _pauseManager, _componentManager, _prototypeManager);
|
||||
var context = new MapContext(_mapManager, _tileDefinitionManager, _serverEntityManager, _pauseManager,
|
||||
_componentManager, _prototypeManager);
|
||||
context.RegisterGrid(grid);
|
||||
var root = context.Serialize();
|
||||
var document = new YamlDocument(root);
|
||||
@@ -68,6 +72,11 @@ namespace Robust.Server.Maps
|
||||
|
||||
/// <inheritdoc />
|
||||
public IMapGrid? LoadBlueprint(MapId mapId, string path)
|
||||
{
|
||||
return LoadBlueprint(mapId, path, DefaultLoadOptions);
|
||||
}
|
||||
|
||||
public IMapGrid? LoadBlueprint(MapId mapId, string path, MapLoadOptions options)
|
||||
{
|
||||
TextReader reader;
|
||||
var resPath = new ResourcePath(path).ToRootedPath();
|
||||
@@ -108,7 +117,8 @@ namespace Robust.Server.Maps
|
||||
throw new InvalidDataException("Cannot instance map with multiple grids as blueprint.");
|
||||
}
|
||||
|
||||
var context = new MapContext(_mapManager, _tileDefinitionManager, _serverEntityManager, _pauseManager, _componentManager, _prototypeManager, (YamlMappingNode)data.RootNode, mapId);
|
||||
var context = new MapContext(_mapManager, _tileDefinitionManager, _serverEntityManager, _pauseManager,
|
||||
_componentManager, _prototypeManager, (YamlMappingNode) data.RootNode, mapId, options);
|
||||
context.Deserialize();
|
||||
grid = context.Grids[0];
|
||||
|
||||
@@ -119,6 +129,14 @@ namespace Robust.Server.Maps
|
||||
entity.RunMapInit();
|
||||
}
|
||||
}
|
||||
|
||||
if (_pauseManager.IsMapPaused(mapId))
|
||||
{
|
||||
foreach (var entity in context.Entities)
|
||||
{
|
||||
entity.Paused = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return grid;
|
||||
@@ -128,7 +146,8 @@ namespace Robust.Server.Maps
|
||||
public void SaveMap(MapId mapId, string yamlPath)
|
||||
{
|
||||
Logger.InfoS("map", $"Saving map {mapId} to {yamlPath}");
|
||||
var context = new MapContext(_mapManager, _tileDefinitionManager, _serverEntityManager, _pauseManager, _componentManager, _prototypeManager);
|
||||
var context = new MapContext(_mapManager, _tileDefinitionManager, _serverEntityManager, _pauseManager,
|
||||
_componentManager, _prototypeManager);
|
||||
foreach (var grid in _mapManager.GetAllMapGrids(mapId))
|
||||
{
|
||||
context.RegisterGrid(grid);
|
||||
@@ -149,11 +168,16 @@ namespace Robust.Server.Maps
|
||||
stream.Save(new YamlMappingFix(new Emitter(writer)), false);
|
||||
}
|
||||
}
|
||||
|
||||
Logger.InfoS("map", "Save completed!");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void LoadMap(MapId mapId, string path)
|
||||
{
|
||||
LoadMap(mapId, path, DefaultLoadOptions);
|
||||
}
|
||||
|
||||
public void LoadMap(MapId mapId, string path, MapLoadOptions options)
|
||||
{
|
||||
TextReader reader;
|
||||
var resPath = new ResourcePath(path).ToRootedPath();
|
||||
@@ -188,7 +212,8 @@ namespace Robust.Server.Maps
|
||||
|
||||
LoadedMapData?.Invoke(data.Stream, resPath.ToString());
|
||||
|
||||
var context = new MapContext(_mapManager, _tileDefinitionManager, _serverEntityManager, _pauseManager, _componentManager, _prototypeManager, (YamlMappingNode)data.RootNode, mapId);
|
||||
var context = new MapContext(_mapManager, _tileDefinitionManager, _serverEntityManager, _pauseManager,
|
||||
_componentManager, _prototypeManager, (YamlMappingNode) data.RootNode, mapId, options);
|
||||
context.Deserialize();
|
||||
|
||||
if (!context.MapIsPostInit && _pauseManager.IsMapInitialized(mapId))
|
||||
@@ -213,6 +238,7 @@ namespace Robust.Server.Maps
|
||||
private readonly IComponentManager _componentManager;
|
||||
private readonly IPrototypeManager _prototypeManager;
|
||||
|
||||
private readonly MapLoadOptions? _loadOptions;
|
||||
private readonly Dictionary<GridId, int> GridIDMap = new();
|
||||
public readonly List<IMapGrid> Grids = new();
|
||||
|
||||
@@ -225,8 +251,6 @@ namespace Robust.Server.Maps
|
||||
|
||||
private bool IsBlueprintMode => GridIDMap.Count == 1;
|
||||
|
||||
private int uidCounter;
|
||||
|
||||
private readonly YamlMappingNode RootNode;
|
||||
private readonly MapId TargetMap;
|
||||
|
||||
@@ -239,7 +263,9 @@ namespace Robust.Server.Maps
|
||||
|
||||
public bool MapIsPostInit { get; private set; }
|
||||
|
||||
public MapContext(IMapManagerInternal maps, ITileDefinitionManager tileDefs, IServerEntityManagerInternal entities, IPauseManager pauseManager, IComponentManager componentManager, IPrototypeManager prototypeManager)
|
||||
public MapContext(IMapManagerInternal maps, ITileDefinitionManager tileDefs,
|
||||
IServerEntityManagerInternal entities, IPauseManager pauseManager, IComponentManager componentManager,
|
||||
IPrototypeManager prototypeManager)
|
||||
{
|
||||
_mapManager = maps;
|
||||
_tileDefinitionManager = tileDefs;
|
||||
@@ -251,14 +277,17 @@ namespace Robust.Server.Maps
|
||||
RootNode = new YamlMappingNode();
|
||||
}
|
||||
|
||||
public MapContext(IMapManagerInternal maps, ITileDefinitionManager tileDefs, IServerEntityManagerInternal entities,
|
||||
IPauseManager pauseManager, IComponentManager componentManager, IPrototypeManager prototypeManager, YamlMappingNode node, MapId targetMapId)
|
||||
public MapContext(IMapManagerInternal maps, ITileDefinitionManager tileDefs,
|
||||
IServerEntityManagerInternal entities,
|
||||
IPauseManager pauseManager, IComponentManager componentManager, IPrototypeManager prototypeManager,
|
||||
YamlMappingNode node, MapId targetMapId, MapLoadOptions options)
|
||||
{
|
||||
_mapManager = maps;
|
||||
_tileDefinitionManager = tileDefs;
|
||||
_serverEntityManager = entities;
|
||||
_pauseManager = pauseManager;
|
||||
_componentManager = componentManager;
|
||||
_loadOptions = options;
|
||||
|
||||
RootNode = node;
|
||||
TargetMap = targetMapId;
|
||||
@@ -438,8 +467,8 @@ namespace Robust.Server.Maps
|
||||
var newId = new GridId?();
|
||||
YamlGridSerializer.DeserializeGrid(
|
||||
_mapManager, TargetMap, ref newId,
|
||||
(YamlMappingNode)grid["settings"],
|
||||
(YamlSequenceNode)grid["chunks"],
|
||||
(YamlMappingNode) grid["settings"],
|
||||
(YamlSequenceNode) grid["chunks"],
|
||||
_tileMap!,
|
||||
_tileDefinitionManager
|
||||
);
|
||||
@@ -489,6 +518,12 @@ namespace Robust.Server.Maps
|
||||
Entities.Add(entity);
|
||||
UidEntityMap.Add(uid, entity.Uid);
|
||||
_entitiesToDeserialize.Add((entity, entityDef));
|
||||
|
||||
if (_loadOptions!.StoreMapUids)
|
||||
{
|
||||
var comp = entity.AddComponent<MapSaveIdComponent>();
|
||||
comp.Uid = uid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -501,7 +536,7 @@ namespace Robust.Server.Maps
|
||||
{
|
||||
foreach (var compData in componentList)
|
||||
{
|
||||
CurrentReadingEntityComponents[compData["type"].AsString()] = (YamlMappingNode)compData;
|
||||
CurrentReadingEntityComponents[compData["type"].AsString()] = (YamlMappingNode) compData;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -605,15 +640,55 @@ namespace Robust.Server.Maps
|
||||
|
||||
private void PopulateEntityList()
|
||||
{
|
||||
var withUid = new List<MapSaveIdComponent>();
|
||||
var withoutUid = new List<IEntity>();
|
||||
var takenIds = new HashSet<int>();
|
||||
|
||||
foreach (var entity in _serverEntityManager.GetEntities())
|
||||
{
|
||||
if (IsMapSavable(entity))
|
||||
{
|
||||
var uid = uidCounter++;
|
||||
EntityUidMap.Add(entity.Uid, uid);
|
||||
Entities.Add(entity);
|
||||
if (entity.TryGetComponent(out MapSaveIdComponent? mapSaveId))
|
||||
{
|
||||
withUid.Add(mapSaveId);
|
||||
}
|
||||
else
|
||||
{
|
||||
withoutUid.Add(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Go over entities with a MapSaveIdComponent and assign those.
|
||||
|
||||
foreach (var mapIdComp in withUid)
|
||||
{
|
||||
var uid = mapIdComp.Uid;
|
||||
if (takenIds.Contains(uid))
|
||||
{
|
||||
// Duplicate ID. Just pretend it doesn't have an ID and use the without path.
|
||||
withoutUid.Add(mapIdComp.Owner);
|
||||
}
|
||||
else
|
||||
{
|
||||
EntityUidMap.Add(mapIdComp.Owner.Uid, uid);
|
||||
takenIds.Add(uid);
|
||||
}
|
||||
}
|
||||
|
||||
var uidCounter = 0;
|
||||
foreach (var entity in withoutUid)
|
||||
{
|
||||
while (takenIds.Contains(uidCounter))
|
||||
{
|
||||
// Find next available UID.
|
||||
uidCounter += 1;
|
||||
}
|
||||
|
||||
EntityUidMap.Add(entity.Uid, uidCounter);
|
||||
takenIds.Add(uidCounter);
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteEntitySection()
|
||||
@@ -621,7 +696,7 @@ namespace Robust.Server.Maps
|
||||
var entities = new YamlSequenceNode();
|
||||
RootNode.Add("entities", entities);
|
||||
|
||||
foreach (var entity in Entities)
|
||||
foreach (var entity in Entities.OrderBy(e => EntityUidMap[e.Uid]))
|
||||
{
|
||||
CurrentWritingEntity = entity;
|
||||
var mapping = new YamlMappingNode
|
||||
@@ -638,6 +713,9 @@ namespace Robust.Server.Maps
|
||||
// See engine#636 for why the Distinct() call.
|
||||
foreach (var component in entity.GetAllComponents())
|
||||
{
|
||||
if (component is MapSaveIdComponent)
|
||||
continue;
|
||||
|
||||
var compMapping = new YamlMappingNode();
|
||||
CurrentWritingComponent = component.Name;
|
||||
var compSerializer = YamlObjectSerializer.NewWriter(compMapping, this);
|
||||
@@ -683,6 +761,7 @@ namespace Robust.Server.Maps
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (type == typeof(EntityUid))
|
||||
{
|
||||
if (node.AsString() == "null")
|
||||
@@ -694,7 +773,8 @@ namespace Robust.Server.Maps
|
||||
var val = node.AsInt();
|
||||
if (val >= Entities.Count)
|
||||
{
|
||||
Logger.ErrorS("map", "Error in map file: found local entity UID '{0}' which does not exist.", val);
|
||||
Logger.ErrorS("map", "Error in map file: found local entity UID '{0}' which does not exist.",
|
||||
val);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -702,12 +782,14 @@ namespace Robust.Server.Maps
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof(IEntity).IsAssignableFrom(type))
|
||||
{
|
||||
var val = node.AsInt();
|
||||
if (val >= Entities.Count)
|
||||
{
|
||||
Logger.ErrorS("map", "Error in map file: found local entity UID '{0}' which does not exist.", val);
|
||||
Logger.ErrorS("map", "Error in map file: found local entity UID '{0}' which does not exist.",
|
||||
val);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -715,6 +797,7 @@ namespace Robust.Server.Maps
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
obj = null;
|
||||
return false;
|
||||
}
|
||||
@@ -766,6 +849,7 @@ namespace Robust.Server.Maps
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
node = null;
|
||||
return false;
|
||||
}
|
||||
@@ -878,7 +962,7 @@ namespace Robust.Server.Maps
|
||||
}
|
||||
|
||||
Stream = stream;
|
||||
GridCount = ((YamlSequenceNode)RootNode["grids"]).Children.Count;
|
||||
GridCount = ((YamlSequenceNode) RootNode["grids"]).Children.Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
using Robust.Server.Console;
|
||||
using Robust.Server.Console;
|
||||
using Robust.Server.DataMetrics;
|
||||
using Robust.Server.Debugging;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Server.GameStates;
|
||||
using Robust.Server.Interfaces;
|
||||
using Robust.Server.Interfaces.Console;
|
||||
using Robust.Server.Interfaces.Debugging;
|
||||
using Robust.Server.Interfaces.GameObjects;
|
||||
using Robust.Server.Interfaces.GameState;
|
||||
@@ -50,7 +49,7 @@ namespace Robust.Server
|
||||
IoCManager.Register<IBaseServerInternal, BaseServer>();
|
||||
IoCManager.Register<IComponentFactory, ServerComponentFactory>();
|
||||
IoCManager.Register<IConGroupController, ConGroupController>();
|
||||
IoCManager.Register<IConsoleShell, ConsoleShell>();
|
||||
IoCManager.Register<IServerConsoleHost, ServerConsoleHost>();
|
||||
IoCManager.Register<IEntityManager, ServerEntityManager>();
|
||||
IoCManager.Register<IEntityNetworkManager, ServerEntityNetworkManager>();
|
||||
IoCManager.Register<IServerEntityNetworkManager, ServerEntityNetworkManager>();
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Robust.Server.GameObjects.Components.Markers;
|
||||
using Robust.Server.Interfaces.GameObjects;
|
||||
using Robust.Server.Interfaces.Timing;
|
||||
using Robust.Shared.GameObjects.Components;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.Interfaces.Map;
|
||||
using Robust.Shared.IoC;
|
||||
@@ -26,7 +26,6 @@ namespace Robust.Server.Timing
|
||||
_pausedMaps.Add(mapId);
|
||||
foreach (var entity in _entityManager.GetEntitiesInMap(mapId))
|
||||
{
|
||||
if (entity.HasComponent<IgnorePauseComponent>()) continue;
|
||||
entity.Paused = true;
|
||||
}
|
||||
}
|
||||
@@ -60,7 +59,7 @@ namespace Robust.Server.Timing
|
||||
public void DoGridMapInitialize(GridId gridId)
|
||||
{
|
||||
var mapId = _mapManager.GetGrid(gridId).ParentMapId;
|
||||
|
||||
|
||||
foreach (var entity in _entityManager.GetEntitiesInMap(mapId))
|
||||
{
|
||||
if (entity.Transform.GridID != gridId)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user