Fix toolshed commands not working on reconnect (#4766)

* Fix toolshed commands not working on reconnect

* fix tests?

* space

* I love #if block errors
This commit is contained in:
Leon Friedrich
2023-12-27 16:48:33 -05:00
committed by GitHub
parent e6ab61fe42
commit 0611674915
8 changed files with 63 additions and 20 deletions

View File

@@ -9,6 +9,7 @@ using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
using Robust.Shared.Network;
using Robust.Shared.Player;
using Robust.Shared.Prototypes;
using Robust.Shared.Toolshed;
@@ -260,6 +261,7 @@ namespace Robust.Shared.Scripting
return true; // Do as I say!
}
public NetUserId? User => null;
public ICommonSession? Session => null;
public void WriteLine(string line)

View File

@@ -17,7 +17,7 @@ internal sealed class DoCommand : ToolshedCommand
[PipedArgument] IEnumerable<T> input,
[CommandArgument] string command)
{
if (ctx is not OldShellInvocationContext { } reqCtx)
if (ctx is not OldShellInvocationContext { } reqCtx || reqCtx.Shell == null)
{
throw new NotImplementedException("do can only be executed in a shell invocation context. Some commands like emplace provide their own context.");
}

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using Robust.Shared.GameObjects;
using Robust.Shared.Network;
using Robust.Shared.Player;
using Robust.Shared.Toolshed.Errors;
using Robust.Shared.Toolshed.Syntax;
@@ -50,6 +51,8 @@ internal record EmplaceContext<T>(IInvocationContext Inner, T Value, IEntityMana
public ICommonSession? Session => Inner.Session;
public ToolshedManager Toolshed => Inner.Toolshed;
public NetUserId? User => Inner.User;
public ToolshedEnvironment Environment => Inner.Environment;
public void WriteLine(string line)

View File

@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Linq;
using Robust.Shared.Network;
using Robust.Shared.Player;
using Robust.Shared.Toolshed.Errors;
using Robust.Shared.Toolshed.Syntax;
@@ -27,6 +28,8 @@ internal record ReduceContext<T>(IInvocationContext Inner, T Value) : IInvocatio
public ICommonSession? Session => Inner.Session;
public ToolshedManager Toolshed => Inner.Toolshed;
public NetUserId? User => Inner.User;
public ToolshedEnvironment Environment => Inner.Environment;
public void WriteLine(string line)

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using Robust.Shared.Network;
using Robust.Shared.Player;
using Robust.Shared.Toolshed.Errors;
using Robust.Shared.Utility;
@@ -33,10 +34,15 @@ public interface IInvocationContext
ToolshedEnvironment Environment { get; }
/// <summary>
/// The session this context is for, if any.
/// The session for the <see cref="User"/>, if any currently exists.
/// </summary>
ICommonSession? Session { get; }
/// <summary>
/// The session this context is for, if any.
/// </summary>
NetUserId? User { get; }
ToolshedManager Toolshed { get; }
/// <summary>

View File

@@ -1,6 +1,7 @@
using System.Collections.Generic;
using Robust.Shared.Console;
using Robust.Shared.IoC;
using Robust.Shared.Network;
using Robust.Shared.Player;
using Robust.Shared.Toolshed.Errors;
using Robust.Shared.Utility;
@@ -18,29 +19,33 @@ internal sealed class OldShellInvocationContext : IInvocationContext
private readonly List<IConError> _errors = new();
/// <summary>
/// Old system's shell associated with this context
/// Old system's shell associated with this context. May be null if the player is currently disconnected.
/// </summary>
public IConsoleShell Shell;
public IConsoleShell? Shell;
public OldShellInvocationContext(IConsoleShell shell)
{
IoCManager.InjectDependencies(this);
Shell = shell;
User = Session?.UserId;
}
/// <inheritdoc />
public ICommonSession? Session => Shell.Player;
public NetUserId? User { get; }
/// <inheritdoc />
public ICommonSession? Session => Shell?.Player;
/// <inheritdoc />
public void WriteLine(string line)
{
Shell.WriteLine(line);
Shell?.WriteLine(line);
}
/// <inheritdoc />
public void WriteLine(FormattedMessage line)
{
Shell.WriteLine(line);
Shell?.WriteLine(line);
}
/// <inheritdoc />

View File

@@ -1,16 +1,12 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Threading.Tasks;
using System.Collections.Generic;
using Robust.Shared.Console;
using Robust.Shared.Enums;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Network;
using Robust.Shared.Player;
using Robust.Shared.Reflection;
using Robust.Shared.Timing;
using Robust.Shared.Toolshed.Invocation;
using Robust.Shared.Toolshed.Syntax;
using Robust.Shared.Toolshed.TypeParsers;
@@ -30,10 +26,16 @@ public sealed partial class ToolshedManager
[Dependency] private readonly IEntityManager _entity = default!;
[Dependency] private readonly IReflectionManager _reflection = default!;
[Dependency] private readonly ILogManager _logManager = default!;
#if !CLIENT_SCRIPTING
[Dependency] private readonly INetManager _net = default!;
#endif
[Dependency] private readonly ISharedPlayerManager _player = default!;
[Dependency] private readonly IConsoleHost _conHost = default!;
private ISawmill _log = default!;
private Dictionary<NetUserId, OldShellInvocationContext> _contexts = new();
/// <summary>
/// If you're not an engine developer, you probably shouldn't call this.
/// </summary>
@@ -42,9 +44,28 @@ public sealed partial class ToolshedManager
_log = _logManager.GetSawmill("toolshed");
InitializeParser();
_player.PlayerStatusChanged += OnStatusChanged;
}
private Dictionary<NetUserId, IInvocationContext> _contexts = new();
private void OnStatusChanged(object? sender, SessionStatusEventArgs e)
{
if (!_contexts.TryGetValue(e.Session.UserId, out var ctx))
return;
DebugTools.Assert(ctx.User == e.Session.UserId);
if (e.NewStatus == SessionStatus.Disconnected)
{
DebugTools.Assert(ctx.Session == e.Session);
ctx.Shell = null;
}
if (e.NewStatus == SessionStatus.InGame)
{
DebugTools.AssertNull(ctx.Session);
DebugTools.AssertNull(ctx.Shell);
ctx.Shell = new ConsoleShell(_conHost, e.Session, false);
}
}
/// <summary>
/// Invokes a command as the given user.
@@ -85,12 +106,12 @@ public sealed partial class ToolshedManager
/// <param name="input">An input value to use, if any.</param>
/// <param name="result">The resulting value, if any.</param>
/// <returns>Invocation success.</returns>
/// <example><code>
/// ToolshedManager toolshed = ...;
/// IConsoleShell ctx = ...;
/// // Now run some user provided command and get a result!
/// toolshed.InvokeCommand(ctx, userCommand, "my input value", out var result);
/// </code></example>
/// <example><code>
/// ToolshedManager toolshed = ...;
/// IConsoleShell ctx = ...;
/// // Now run some user provided command and get a result!
/// toolshed.InvokeCommand(ctx, userCommand, "my input value", out var result);
/// </code></example>
/// <remarks>
/// This will use the same IInvocationContext as the one used by the user for debug console commands.
/// </remarks>

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using NUnit.Framework;
using Robust.Shared.Network;
using Robust.Shared.Player;
using Robust.Shared.Toolshed;
using Robust.Shared.Toolshed.Errors;
@@ -102,6 +103,8 @@ public abstract class ToolshedTest : RobustIntegrationTest, IInvocationContext
protected ICommonSession? InvocationSession { get; set; }
public NetUserId? User => Session?.UserId;
public ICommonSession? Session
{
get