Toolshed (#17895)
* ogh * i should save my work * ogh * hhcdfhjbghshbxdfhghshc - lots of bugs in parsing still - invocation is a stub * expr parsing works * awawa * Saving work * Improve APIs a bit all around, add shortcuts. * awa * awa * AAAAAA * save work * Move shit to engine * lord * bql is kill * forgot the fucking bike rack * bql is kill for real * pjb will kill me * aughfhbdj * adgddf * gdsgvfvxshngfgh * b * hfsjhghj * a * tf you mean i have to document it * follow C# standards * Assorted cleanup and documentation pass, minor bugfix in ValueRefParser. * Start porting old commands, remove that pesky prefix in favor of integrating with the shell. * bw * Fix valueref up a bit, improve autocomplete for it. * awa * fix tests * git shut up * Arithmetic commands. * parse improvements * Update engine. --------- Co-authored-by: moonheart08 <moonheart08@users.noreply.github.com>
This commit is contained in:
@@ -7,13 +7,13 @@ using Robust.Client.Console;
|
|||||||
namespace Content.Client.Bql;
|
namespace Content.Client.Bql;
|
||||||
|
|
||||||
[UsedImplicitly]
|
[UsedImplicitly]
|
||||||
public sealed class BqlResultsEui : BaseEui
|
public sealed class ToolshedVisualizeEui : BaseEui
|
||||||
{
|
{
|
||||||
private readonly BqlResultsWindow _window;
|
private readonly ToolshedVisualizeWindow _window;
|
||||||
|
|
||||||
public BqlResultsEui()
|
public ToolshedVisualizeEui()
|
||||||
{
|
{
|
||||||
_window = new BqlResultsWindow(
|
_window = new ToolshedVisualizeWindow(
|
||||||
IoCManager.Resolve<IClientConsoleHost>(),
|
IoCManager.Resolve<IClientConsoleHost>(),
|
||||||
IoCManager.Resolve<ILocalizationManager>()
|
IoCManager.Resolve<ILocalizationManager>()
|
||||||
);
|
);
|
||||||
@@ -23,7 +23,7 @@ public sealed class BqlResultsEui : BaseEui
|
|||||||
|
|
||||||
public override void HandleState(EuiStateBase state)
|
public override void HandleState(EuiStateBase state)
|
||||||
{
|
{
|
||||||
if (state is not BqlResultsEuiState castState)
|
if (state is not ToolshedVisualizeEuiState castState)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_window.Update(castState.Entities);
|
_window.Update(castState.Entities);
|
||||||
@@ -8,12 +8,12 @@ using Robust.Client.UserInterface.XAML;
|
|||||||
namespace Content.Client.Bql;
|
namespace Content.Client.Bql;
|
||||||
|
|
||||||
[GenerateTypedNameReferences]
|
[GenerateTypedNameReferences]
|
||||||
internal sealed partial class BqlResultsWindow : DefaultWindow
|
internal sealed partial class ToolshedVisualizeWindow : DefaultWindow
|
||||||
{
|
{
|
||||||
private readonly IClientConsoleHost _console;
|
private readonly IClientConsoleHost _console;
|
||||||
private readonly ILocalizationManager _loc;
|
private readonly ILocalizationManager _loc;
|
||||||
|
|
||||||
public BqlResultsWindow(IClientConsoleHost console, ILocalizationManager loc)
|
public ToolshedVisualizeWindow(IClientConsoleHost console, ILocalizationManager loc)
|
||||||
{
|
{
|
||||||
_console = console;
|
_console = console;
|
||||||
_loc = loc;
|
_loc = loc;
|
||||||
@@ -33,6 +33,9 @@
|
|||||||
<Compile Update="UserInterface\Systems\Inventory\Windows\StrippingWindow.xaml.cs">
|
<Compile Update="UserInterface\Systems\Inventory\Windows\StrippingWindow.xaml.cs">
|
||||||
<DependentUpon>StrippingWindow.xaml</DependentUpon>
|
<DependentUpon>StrippingWindow.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Update="Bql\ToolshedVisualizeWindow.xaml.cs">
|
||||||
|
<DependentUpon>ToolshedVisualizeWindow.xaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<Import Project="..\RobustToolbox\MSBuild\Robust.Properties.targets" />
|
<Import Project="..\RobustToolbox\MSBuild\Robust.Properties.targets" />
|
||||||
|
|||||||
@@ -162,6 +162,7 @@ namespace Content.Client.Stylesheets
|
|||||||
var notoSansBold16 = resCache.NotoStack(variation: "Bold", size: 16);
|
var notoSansBold16 = resCache.NotoStack(variation: "Bold", size: 16);
|
||||||
var notoSansBold18 = resCache.NotoStack(variation: "Bold", size: 18);
|
var notoSansBold18 = resCache.NotoStack(variation: "Bold", size: 18);
|
||||||
var notoSansBold20 = resCache.NotoStack(variation: "Bold", size: 20);
|
var notoSansBold20 = resCache.NotoStack(variation: "Bold", size: 20);
|
||||||
|
var notoSansMono = resCache.GetFont("/EngineFonts/NotoSans/NotoSansMono-Regular.ttf", size: 12);
|
||||||
var windowHeaderTex = resCache.GetTexture("/Textures/Interface/Nano/window_header.png");
|
var windowHeaderTex = resCache.GetTexture("/Textures/Interface/Nano/window_header.png");
|
||||||
var windowHeader = new StyleBoxTexture
|
var windowHeader = new StyleBoxTexture
|
||||||
{
|
{
|
||||||
@@ -512,6 +513,8 @@ namespace Content.Client.Stylesheets
|
|||||||
|
|
||||||
Stylesheet = new Stylesheet(BaseRules.Concat(new[]
|
Stylesheet = new Stylesheet(BaseRules.Concat(new[]
|
||||||
{
|
{
|
||||||
|
Element().Class("monospace")
|
||||||
|
.Prop("font", notoSansMono),
|
||||||
// Window title.
|
// Window title.
|
||||||
new StyleRule(
|
new StyleRule(
|
||||||
new SelectorElement(typeof(Label), new[] {DefaultWindow.StyleClassWindowTitle}, null, null),
|
new SelectorElement(typeof(Label), new[] {DefaultWindow.StyleClassWindowTitle}, null, null),
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Content.Server.Administration.Commands;
|
using Content.Server.Administration.Commands;
|
||||||
|
using Content.Server.Administration.Systems;
|
||||||
using Content.Shared.Damage;
|
using Content.Shared.Damage;
|
||||||
using Content.Shared.Damage.Prototypes;
|
using Content.Shared.Damage.Prototypes;
|
||||||
using Content.Shared.FixedPoint;
|
using Content.Shared.FixedPoint;
|
||||||
@@ -11,7 +12,7 @@ using Robust.Shared.Prototypes;
|
|||||||
namespace Content.IntegrationTests.Tests.Commands
|
namespace Content.IntegrationTests.Tests.Commands
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
[TestOf(typeof(RejuvenateCommand))]
|
[TestOf(typeof(RejuvenateSystem))]
|
||||||
public sealed class RejuvenateTest
|
public sealed class RejuvenateTest
|
||||||
{
|
{
|
||||||
private const string Prototypes = @"
|
private const string Prototypes = @"
|
||||||
@@ -42,6 +43,7 @@ namespace Content.IntegrationTests.Tests.Commands
|
|||||||
var prototypeManager = server.ResolveDependency<IPrototypeManager>();
|
var prototypeManager = server.ResolveDependency<IPrototypeManager>();
|
||||||
var mobStateSystem = entManager.EntitySysManager.GetEntitySystem<MobStateSystem>();
|
var mobStateSystem = entManager.EntitySysManager.GetEntitySystem<MobStateSystem>();
|
||||||
var damSystem = entManager.EntitySysManager.GetEntitySystem<DamageableSystem>();
|
var damSystem = entManager.EntitySysManager.GetEntitySystem<DamageableSystem>();
|
||||||
|
var rejuvenateSystem = entManager.EntitySysManager.GetEntitySystem<RejuvenateSystem>();
|
||||||
|
|
||||||
await server.WaitAssertion(() =>
|
await server.WaitAssertion(() =>
|
||||||
{
|
{
|
||||||
@@ -78,7 +80,7 @@ namespace Content.IntegrationTests.Tests.Commands
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Rejuvenate them
|
// Rejuvenate them
|
||||||
RejuvenateCommand.PerformRejuvenate(human);
|
rejuvenateSystem.PerformRejuvenate(human);
|
||||||
|
|
||||||
// Check that it is alive and with no damage
|
// Check that it is alive and with no damage
|
||||||
Assert.Multiple(() =>
|
Assert.Multiple(() =>
|
||||||
|
|||||||
20
Content.IntegrationTests/Tests/Toolshed/AdminTest.cs
Normal file
20
Content.IntegrationTests/Tests/Toolshed/AdminTest.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Robust.Shared.Toolshed;
|
||||||
|
|
||||||
|
namespace Content.IntegrationTests.Tests.Toolshed;
|
||||||
|
|
||||||
|
[TestFixture]
|
||||||
|
public sealed class AdminTest : ToolshedTest
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public async Task AllCommandsHavePermissions()
|
||||||
|
{
|
||||||
|
await Server.WaitAssertion(() =>
|
||||||
|
{
|
||||||
|
Assert.That(InvokeCommand("cmd:list where { acmd:perms isnull }", out var res));
|
||||||
|
var list = ((IEnumerable<CommandSpec>) res).ToList();
|
||||||
|
Assert.That(list, Is.Empty, "All commands must have admin permissions set up.");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
84
Content.IntegrationTests/Tests/Toolshed/CommandParseTest.cs
Normal file
84
Content.IntegrationTests/Tests/Toolshed/CommandParseTest.cs
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.Toolshed;
|
||||||
|
using Robust.Shared.Toolshed.Syntax;
|
||||||
|
using Robust.Shared.Toolshed.TypeParsers;
|
||||||
|
|
||||||
|
namespace Content.IntegrationTests.Tests.Toolshed;
|
||||||
|
|
||||||
|
[TestFixture]
|
||||||
|
public sealed class CommandRunTest : ToolshedTest
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public async Task SimpleCommandRun()
|
||||||
|
{
|
||||||
|
await Server.WaitAssertion(() =>
|
||||||
|
{
|
||||||
|
ParseCommand("entities");
|
||||||
|
ParseCommand("entities select 1");
|
||||||
|
ParseCommand("entities with Item select 1");
|
||||||
|
|
||||||
|
ExpectError<OutOfInputError>();
|
||||||
|
ParseCommand("entities with");
|
||||||
|
|
||||||
|
ExpectError<NoImplementationError>();
|
||||||
|
ParseCommand("player:list with MetaData");
|
||||||
|
|
||||||
|
ExpectError<ExpressionOfWrongType>();
|
||||||
|
ParseCommand("player:list", expectedType: typeof(IEnumerable<EntityUid>));
|
||||||
|
|
||||||
|
ParseCommand("entities not with MetaData");
|
||||||
|
ParseCommand("with MetaData select 2 any", inputType: typeof(List<EntityUid>));
|
||||||
|
|
||||||
|
ParseCommand("entities not with MetaData => $myEntities");
|
||||||
|
ParseCommand("=> $fooBar with MetaData", inputType: typeof(List<EntityUid>));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task EntityUidTypeParser()
|
||||||
|
{
|
||||||
|
await Server.WaitAssertion(() =>
|
||||||
|
{
|
||||||
|
ParseCommand("ent 1");
|
||||||
|
ParseCommand("ent c1");
|
||||||
|
|
||||||
|
ExpectError<InvalidEntityUid>();
|
||||||
|
ParseCommand("ent foodigity");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task QuantityTypeParser()
|
||||||
|
{
|
||||||
|
await Server.WaitAssertion(() =>
|
||||||
|
{
|
||||||
|
ParseCommand("entities select 100");
|
||||||
|
ParseCommand("entities select 50%");
|
||||||
|
|
||||||
|
ExpectError<InvalidQuantity>();
|
||||||
|
ParseCommand("entities select -1");
|
||||||
|
|
||||||
|
ExpectError<InvalidQuantity>();
|
||||||
|
ParseCommand("entities select 200%");
|
||||||
|
|
||||||
|
ExpectError<InvalidQuantity>();
|
||||||
|
ParseCommand("entities select hotdog");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task ComponentTypeParser()
|
||||||
|
{
|
||||||
|
await Server.WaitAssertion(() =>
|
||||||
|
{
|
||||||
|
ParseCommand("entities with MetaData");
|
||||||
|
|
||||||
|
ExpectError<UnknownComponentError>();
|
||||||
|
ParseCommand("entities with Foodiddy");
|
||||||
|
|
||||||
|
ExpectError<UnknownComponentError>();
|
||||||
|
ParseCommand("entities with MetaDataComponent");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
19
Content.IntegrationTests/Tests/Toolshed/LocTest.cs
Normal file
19
Content.IntegrationTests/Tests/Toolshed/LocTest.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Robust.Shared.Toolshed;
|
||||||
|
|
||||||
|
namespace Content.IntegrationTests.Tests.Toolshed;
|
||||||
|
|
||||||
|
[TestFixture]
|
||||||
|
public sealed class LocTest : ToolshedTest
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public async Task AllCommandsHaveDescriptions()
|
||||||
|
{
|
||||||
|
await Server.WaitAssertion(() =>
|
||||||
|
{
|
||||||
|
Assert.That(InvokeCommand("cmd:list where { cmd:descloc loc:tryloc isnull }", out var res));
|
||||||
|
Assert.That((IEnumerable<CommandSpec>)res, Is.Empty, "All commands must have localized descriptions.");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
153
Content.IntegrationTests/Tests/Toolshed/ToolshedTest.cs
Normal file
153
Content.IntegrationTests/Tests/Toolshed/ToolshedTest.cs
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
#nullable enable
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Content.Server.Administration.Managers;
|
||||||
|
using Robust.Server.Player;
|
||||||
|
using Robust.Shared.Players;
|
||||||
|
using Robust.Shared.Toolshed;
|
||||||
|
using Robust.Shared.Toolshed.Errors;
|
||||||
|
using Robust.Shared.Toolshed.Syntax;
|
||||||
|
using Robust.UnitTesting;
|
||||||
|
|
||||||
|
namespace Content.IntegrationTests.Tests.Toolshed;
|
||||||
|
|
||||||
|
[TestFixture]
|
||||||
|
[FixtureLifeCycle(LifeCycle.SingleInstance)]
|
||||||
|
public abstract class ToolshedTest : IInvocationContext
|
||||||
|
{
|
||||||
|
protected PairTracker PairTracker = default!;
|
||||||
|
|
||||||
|
protected virtual bool NoClient => true;
|
||||||
|
protected virtual bool AssertOnUnexpectedError => true;
|
||||||
|
|
||||||
|
protected RobustIntegrationTest.ServerIntegrationInstance Server = default!;
|
||||||
|
protected RobustIntegrationTest.ClientIntegrationInstance? Client = null;
|
||||||
|
protected ToolshedManager Toolshed = default!;
|
||||||
|
protected IAdminManager AdminManager = default!;
|
||||||
|
|
||||||
|
protected IInvocationContext? Context = null;
|
||||||
|
|
||||||
|
[TearDown]
|
||||||
|
public virtual async Task TearDown()
|
||||||
|
{
|
||||||
|
Assert.IsEmpty(_expectedErrors);
|
||||||
|
ClearErrors();
|
||||||
|
}
|
||||||
|
|
||||||
|
[OneTimeSetUp]
|
||||||
|
public virtual async Task Setup()
|
||||||
|
{
|
||||||
|
PairTracker = await PoolManager.GetServerClient(new PoolSettings {NoClient = NoClient});
|
||||||
|
Server = PairTracker.Pair.Server;
|
||||||
|
|
||||||
|
if (!NoClient)
|
||||||
|
{
|
||||||
|
Client = PairTracker.Pair.Client;
|
||||||
|
await Client.WaitIdleAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
await Server.WaitIdleAsync();
|
||||||
|
|
||||||
|
Toolshed = Server.ResolveDependency<ToolshedManager>();
|
||||||
|
AdminManager = Server.ResolveDependency<IAdminManager>();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected bool InvokeCommand(string command, out object? result, IPlayerSession? session = null)
|
||||||
|
{
|
||||||
|
return Toolshed.InvokeCommand(this, command, null, out result);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void ParseCommand(string command, Type? inputType = null, Type? expectedType = null, bool once = false)
|
||||||
|
{
|
||||||
|
var parser = new ForwardParser(command, Toolshed);
|
||||||
|
var success = CommandRun.TryParse(false, false, parser, inputType, expectedType, once, out _, out _, out var error);
|
||||||
|
|
||||||
|
if (error is not null)
|
||||||
|
ReportError(error);
|
||||||
|
|
||||||
|
if (error is null)
|
||||||
|
Assert.That(success, $"Parse failed despite no error being reported. Parsed {command}");
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CheckInvokable(CommandSpec command, out IConError? error)
|
||||||
|
{
|
||||||
|
if (Context is not null)
|
||||||
|
{
|
||||||
|
return Context.CheckInvokable(command, out error);
|
||||||
|
}
|
||||||
|
|
||||||
|
error = null;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected IPlayerSession? InvocationSession { get; set; }
|
||||||
|
|
||||||
|
public ICommonSession? Session
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (Context is not null)
|
||||||
|
{
|
||||||
|
return Context.Session;
|
||||||
|
}
|
||||||
|
|
||||||
|
return InvocationSession;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteLine(string line)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Queue<Type> _expectedErrors = new();
|
||||||
|
|
||||||
|
private List<IConError> _errors = new();
|
||||||
|
|
||||||
|
public void ReportError(IConError err)
|
||||||
|
{
|
||||||
|
if (_expectedErrors.Count == 0)
|
||||||
|
{
|
||||||
|
if (AssertOnUnexpectedError)
|
||||||
|
{
|
||||||
|
Assert.Fail($"Got an error, {err.GetType()}, when none was expected.\n{err.Describe()}");
|
||||||
|
}
|
||||||
|
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
var ty = _expectedErrors.Dequeue();
|
||||||
|
|
||||||
|
if (AssertOnUnexpectedError)
|
||||||
|
{
|
||||||
|
Assert.That(
|
||||||
|
err.GetType().IsAssignableTo(ty),
|
||||||
|
$"The error {err.GetType()} wasn't assignable to the expected type {ty}.\n{err.Describe()}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
_errors.Add(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<IConError> GetErrors()
|
||||||
|
{
|
||||||
|
return _errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClearErrors()
|
||||||
|
{
|
||||||
|
_errors.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dictionary<string, object?> Variables { get; } = new();
|
||||||
|
|
||||||
|
protected void ExpectError(Type err)
|
||||||
|
{
|
||||||
|
_expectedErrors.Enqueue(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void ExpectError<T>()
|
||||||
|
{
|
||||||
|
_expectedErrors.Enqueue(typeof(T));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,7 +12,6 @@ namespace Content.Server.Administration
|
|||||||
/// </remarks>
|
/// </remarks>
|
||||||
/// <seealso cref="AnyCommandAttribute"/>
|
/// <seealso cref="AnyCommandAttribute"/>
|
||||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
|
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
|
||||||
[BaseTypeRequired(typeof(IConsoleCommand))]
|
|
||||||
[MeansImplicitUse]
|
[MeansImplicitUse]
|
||||||
public sealed class AdminCommandAttribute : Attribute
|
public sealed class AdminCommandAttribute : Attribute
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,47 +0,0 @@
|
|||||||
using System.Linq;
|
|
||||||
using Content.Shared.Administration;
|
|
||||||
using Robust.Shared.Console;
|
|
||||||
|
|
||||||
namespace Content.Server.Administration.Commands
|
|
||||||
{
|
|
||||||
[AdminCommand(AdminFlags.Spawn)]
|
|
||||||
sealed class DeleteEntitiesWithComponent : IConsoleCommand
|
|
||||||
{
|
|
||||||
public string Command => "deleteewc";
|
|
||||||
|
|
||||||
public string Description => Loc.GetString("delete-entities-with-component-command-description");
|
|
||||||
|
|
||||||
public string Help => Loc.GetString("delete-entities-with-component-command-help-text");
|
|
||||||
|
|
||||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
|
||||||
{
|
|
||||||
if (args.Length < 1)
|
|
||||||
{
|
|
||||||
shell.WriteLine(Help);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var factory = IoCManager.Resolve<IComponentFactory>();
|
|
||||||
|
|
||||||
var components = new List<Type>();
|
|
||||||
foreach (var arg in args)
|
|
||||||
{
|
|
||||||
components.Add(factory.GetRegistration(arg).Type);
|
|
||||||
}
|
|
||||||
|
|
||||||
var entityManager = IoCManager.Resolve<IEntityManager>();
|
|
||||||
|
|
||||||
var entitiesWithComponents = components.Select(c => entityManager.GetAllComponents(c).Select(x => x.Uid));
|
|
||||||
var entitiesWithAllComponents = entitiesWithComponents.Skip(1).Aggregate(new HashSet<EntityUid>(entitiesWithComponents.First()), (h, e) => { h.IntersectWith(e); return h; });
|
|
||||||
|
|
||||||
var count = 0;
|
|
||||||
foreach (var entity in entitiesWithAllComponents)
|
|
||||||
{
|
|
||||||
entityManager.DeleteEntity(entity);
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
shell.WriteLine(Loc.GetString("delete-entities-with-component-command-deleted-components",("count", count)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
using System.Linq;
|
|
||||||
using Content.Shared.Administration;
|
|
||||||
using Robust.Shared.Console;
|
|
||||||
|
|
||||||
namespace Content.Server.Administration.Commands
|
|
||||||
{
|
|
||||||
[AdminCommand(AdminFlags.Spawn)]
|
|
||||||
public sealed class DeleteEntitiesWithId : IConsoleCommand
|
|
||||||
{
|
|
||||||
public string Command => "deleteewi";
|
|
||||||
public string Description => "Deletes entities with the specified prototype ID.";
|
|
||||||
public string Help => $"Usage: {Command} <prototypeID>";
|
|
||||||
|
|
||||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
|
||||||
{
|
|
||||||
if (args.Length != 1)
|
|
||||||
{
|
|
||||||
shell.WriteLine(Help);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var id = args[0].ToLower();
|
|
||||||
var entityManager = IoCManager.Resolve<IEntityManager>();
|
|
||||||
var entities = entityManager.GetEntities().Where(e => entityManager.GetComponent<MetaDataComponent>(e).EntityPrototype?.ID.ToLower() == id);
|
|
||||||
var i = 0;
|
|
||||||
|
|
||||||
foreach (var entity in entities)
|
|
||||||
{
|
|
||||||
entityManager.DeleteEntity(entity);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
shell.WriteLine($"Deleted all entities with id {id}. Occurrences: {i}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
using Content.Shared.Administration;
|
|
||||||
using Robust.Shared.Console;
|
|
||||||
|
|
||||||
namespace Content.Server.Administration.Commands
|
|
||||||
{
|
|
||||||
[AdminCommand(AdminFlags.Spawn)]
|
|
||||||
public sealed class DeleteEntityCommand : IConsoleCommand
|
|
||||||
{
|
|
||||||
public string Command => "deleteentity";
|
|
||||||
public string Description => "Deletes an entity with the given id.";
|
|
||||||
public string Help => $"Usage: {Command} <id>";
|
|
||||||
|
|
||||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
|
||||||
{
|
|
||||||
if (args.Length != 1)
|
|
||||||
{
|
|
||||||
shell.WriteLine($"Invalid amount of arguments.\n{Help}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!EntityUid.TryParse(args[0], out var id))
|
|
||||||
{
|
|
||||||
shell.WriteLine($"{args[0]} is not a valid entity id.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var entityManager = IoCManager.Resolve<IEntityManager>();
|
|
||||||
|
|
||||||
if (!entityManager.EntityExists(id))
|
|
||||||
{
|
|
||||||
shell.WriteLine($"No entity found with id {id}.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
entityManager.DeleteEntity(id);
|
|
||||||
shell.WriteLine($"Deleted entity with id {id}.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
using System.Linq;
|
|
||||||
using Content.Shared.Administration;
|
|
||||||
using Robust.Shared.Console;
|
|
||||||
|
|
||||||
namespace Content.Server.Administration.Commands
|
|
||||||
{
|
|
||||||
[AdminCommand(AdminFlags.Mapping)]
|
|
||||||
public sealed class FindEntitiesWithComponents : IConsoleCommand
|
|
||||||
{
|
|
||||||
public string Command => "findentitieswithcomponents";
|
|
||||||
public string Description => "Finds entities with all of the specified components.";
|
|
||||||
public string Help => $"{Command} <componentName1> <componentName2>...";
|
|
||||||
|
|
||||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
|
||||||
{
|
|
||||||
if (args.Length == 0)
|
|
||||||
{
|
|
||||||
shell.WriteLine($"Invalid amount of arguments: {args.Length}.\n{Help}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var components = new List<Type>();
|
|
||||||
var componentFactory = IoCManager.Resolve<IComponentFactory>();
|
|
||||||
var invalidArgs = new List<string>();
|
|
||||||
|
|
||||||
foreach (var arg in args)
|
|
||||||
{
|
|
||||||
if (!componentFactory.TryGetRegistration(arg, out var registration))
|
|
||||||
{
|
|
||||||
invalidArgs.Add(arg);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
components.Add(registration.Type);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (invalidArgs.Count > 0)
|
|
||||||
{
|
|
||||||
shell.WriteLine($"No component found for component names: {string.Join(", ", invalidArgs)}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var entityManager = IoCManager.Resolve<IEntityManager>();
|
|
||||||
var entityIds = new HashSet<string>();
|
|
||||||
|
|
||||||
var entitiesWithComponents = components.Select(c => entityManager.GetAllComponents(c).Select(x => x.Uid)).ToArray();
|
|
||||||
var entitiesWithAllComponents = entitiesWithComponents.Skip(1).Aggregate(new HashSet<EntityUid>(entitiesWithComponents.First()), (h, e) => { h.IntersectWith(e); return h; });
|
|
||||||
|
|
||||||
foreach (var entity in entitiesWithAllComponents)
|
|
||||||
{
|
|
||||||
if (entityManager.GetComponent<MetaDataComponent>(entity).EntityPrototype is not { } prototypeId)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
entityIds.Add(prototypeId.ID);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entityIds.Count == 0)
|
|
||||||
{
|
|
||||||
shell.WriteLine($"No entities found with components {string.Join(", ", args)}.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
shell.WriteLine($"{entityIds.Count} entities found:\n{string.Join("\n", entityIds)}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
using Content.Shared.Administration;
|
|
||||||
using Content.Shared.Rejuvenate;
|
|
||||||
using Robust.Server.Player;
|
|
||||||
using Robust.Shared.Console;
|
|
||||||
|
|
||||||
namespace Content.Server.Administration.Commands
|
|
||||||
{
|
|
||||||
[AdminCommand(AdminFlags.Admin)]
|
|
||||||
public sealed class RejuvenateCommand : IConsoleCommand
|
|
||||||
{
|
|
||||||
public string Command => "rejuvenate";
|
|
||||||
|
|
||||||
public string Description => Loc.GetString("rejuvenate-command-description");
|
|
||||||
|
|
||||||
public string Help => Loc.GetString("rejuvenate-command-help-text");
|
|
||||||
|
|
||||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
|
||||||
{
|
|
||||||
if (args.Length < 1 && shell.Player is IPlayerSession player) //Try to heal the users mob if applicable
|
|
||||||
{
|
|
||||||
shell.WriteLine(Loc.GetString("rejuvenate-command-self-heal-message"));
|
|
||||||
if (player.AttachedEntity == null)
|
|
||||||
{
|
|
||||||
shell.WriteLine(Loc.GetString("rejuvenate-command-no-entity-attached-message"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
PerformRejuvenate(player.AttachedEntity.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
var entityManager = IoCManager.Resolve<IEntityManager>();
|
|
||||||
foreach (var arg in args)
|
|
||||||
{
|
|
||||||
if (!EntityUid.TryParse(arg, out var entity) || !entityManager.EntityExists(entity))
|
|
||||||
{
|
|
||||||
shell.WriteLine(Loc.GetString("shell-could-not-find-entity",("entity", arg)));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
PerformRejuvenate(entity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void PerformRejuvenate(EntityUid target)
|
|
||||||
{
|
|
||||||
var entityManager = IoCManager.Resolve<IEntityManager>();
|
|
||||||
entityManager.EventBus.RaiseLocalEvent(target, new RejuvenateEvent());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
using Content.Server.Commands;
|
|
||||||
using Content.Server.Station.Components;
|
|
||||||
using Content.Server.Station.Systems;
|
|
||||||
using Content.Shared.Administration;
|
|
||||||
using Content.Shared.Roles;
|
|
||||||
using Robust.Shared.Console;
|
|
||||||
using Robust.Shared.Prototypes;
|
|
||||||
|
|
||||||
namespace Content.Server.Administration.Commands.Station;
|
|
||||||
|
|
||||||
[AdminCommand(AdminFlags.Round)]
|
|
||||||
public sealed class AdjustStationJobCommand : IConsoleCommand
|
|
||||||
{
|
|
||||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
|
||||||
[Dependency] private readonly IEntitySystemManager _entSysManager = default!;
|
|
||||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
|
||||||
|
|
||||||
public string Command => "adjstationjob";
|
|
||||||
|
|
||||||
public string Description => "Adjust the job manifest on a station.";
|
|
||||||
|
|
||||||
public string Help => "adjstationjob <station id> <job id> <amount>";
|
|
||||||
|
|
||||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
|
||||||
{
|
|
||||||
if (args.Length != 3)
|
|
||||||
{
|
|
||||||
shell.WriteError(Loc.GetString("shell-wrong-arguments-number"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var stationJobs = _entSysManager.GetEntitySystem<StationJobsSystem>();
|
|
||||||
|
|
||||||
if (!EntityUid.TryParse(args[0], out var station) || !_entityManager.HasComponent<StationDataComponent>(station))
|
|
||||||
{
|
|
||||||
shell.WriteError(Loc.GetString("shell-argument-station-id-invalid", ("index", 1)));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_prototypeManager.TryIndex<JobPrototype>(args[1], out var job))
|
|
||||||
{
|
|
||||||
shell.WriteError(Loc.GetString("shell-argument-must-be-prototype",
|
|
||||||
("index", 2), ("prototypeName", nameof(JobPrototype))));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!int.TryParse(args[2], out var amount) || amount < -1)
|
|
||||||
{
|
|
||||||
shell.WriteError(Loc.GetString("shell-argument-number-must-be-between",
|
|
||||||
("index", 3), ("lower", -1), ("upper", int.MaxValue)));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (amount == -1)
|
|
||||||
{
|
|
||||||
stationJobs.MakeJobUnlimited(station, job);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
stationJobs.TrySetJobSlot(station, job, amount, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CompletionResult GetCompletion(IConsoleShell shell, string[] args)
|
|
||||||
{
|
|
||||||
if (args.Length == 1)
|
|
||||||
{
|
|
||||||
var options = ContentCompletionHelper.StationIds(_entityManager);
|
|
||||||
return CompletionResult.FromHintOptions(options, "<station id>");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args.Length == 2)
|
|
||||||
{
|
|
||||||
var options = CompletionHelper.PrototypeIDs<JobPrototype>();
|
|
||||||
return CompletionResult.FromHintOptions(options, "<job id>");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args.Length == 3)
|
|
||||||
{
|
|
||||||
return CompletionResult.FromHint("<amount>");
|
|
||||||
}
|
|
||||||
|
|
||||||
return CompletionResult.Empty;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
using Content.Server.Commands;
|
|
||||||
using Content.Server.Station.Components;
|
|
||||||
using Content.Server.Station.Systems;
|
|
||||||
using Content.Shared.Administration;
|
|
||||||
using Robust.Shared.Console;
|
|
||||||
|
|
||||||
namespace Content.Server.Administration.Commands.Station;
|
|
||||||
|
|
||||||
[AdminCommand(AdminFlags.Admin)]
|
|
||||||
public sealed class ListStationJobsCommand : IConsoleCommand
|
|
||||||
{
|
|
||||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
|
||||||
[Dependency] private readonly IEntitySystemManager _entSysManager = default!;
|
|
||||||
|
|
||||||
public string Command => "lsstationjobs";
|
|
||||||
|
|
||||||
public string Description => "Lists all jobs on the given station.";
|
|
||||||
|
|
||||||
public string Help => "lsstationjobs <station id>";
|
|
||||||
|
|
||||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
|
||||||
{
|
|
||||||
if (args.Length != 1)
|
|
||||||
{
|
|
||||||
shell.WriteError(Loc.GetString("shell-wrong-arguments-number"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var stationSystem = _entSysManager.GetEntitySystem<StationSystem>();
|
|
||||||
var stationJobs = _entSysManager.GetEntitySystem<StationJobsSystem>();
|
|
||||||
|
|
||||||
if (!EntityUid.TryParse(args[0], out var station) || !_entityManager.HasComponent<StationJobsComponent>(station))
|
|
||||||
{
|
|
||||||
shell.WriteError(Loc.GetString("shell-argument-station-id-invalid", ("index", 1)));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var (job, amount) in stationJobs.GetJobs(station))
|
|
||||||
{
|
|
||||||
var amountText = amount is null ? "Infinite" : amount.ToString();
|
|
||||||
shell.WriteLine($"{job}: {amountText}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public CompletionResult GetCompletion(IConsoleShell shell, string[] args)
|
|
||||||
{
|
|
||||||
if (args.Length == 1)
|
|
||||||
{
|
|
||||||
var options = ContentCompletionHelper.StationIds(_entityManager);
|
|
||||||
return CompletionResult.FromHintOptions(options, "<station id>");
|
|
||||||
}
|
|
||||||
|
|
||||||
return CompletionResult.Empty;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
using Content.Server.Station.Components;
|
|
||||||
using Content.Server.Station.Systems;
|
|
||||||
using Content.Shared.Administration;
|
|
||||||
using Robust.Shared.Console;
|
|
||||||
|
|
||||||
namespace Content.Server.Administration.Commands.Station;
|
|
||||||
|
|
||||||
[AdminCommand(AdminFlags.Admin)]
|
|
||||||
public sealed class ListStationsCommand : IConsoleCommand
|
|
||||||
{
|
|
||||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
|
||||||
|
|
||||||
public string Command => "lsstations";
|
|
||||||
|
|
||||||
public string Description => "List all active stations";
|
|
||||||
|
|
||||||
public string Help => "lsstations";
|
|
||||||
|
|
||||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
|
||||||
{
|
|
||||||
var query = _entityManager.EntityQueryEnumerator<StationDataComponent>();
|
|
||||||
|
|
||||||
while (query.MoveNext(out var station, out _))
|
|
||||||
{
|
|
||||||
var name = _entityManager.GetComponent<MetaDataComponent>(station).EntityName;
|
|
||||||
shell.WriteLine($"{station, -10} | {name}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
using Content.Server.Commands;
|
|
||||||
using Content.Server.Station.Components;
|
|
||||||
using Content.Server.Station.Systems;
|
|
||||||
using Content.Shared.Administration;
|
|
||||||
using Robust.Shared.Console;
|
|
||||||
|
|
||||||
namespace Content.Server.Administration.Commands.Station;
|
|
||||||
|
|
||||||
[AdminCommand(AdminFlags.Admin)]
|
|
||||||
public sealed class RenameStationCommand : IConsoleCommand
|
|
||||||
{
|
|
||||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
|
||||||
[Dependency] private readonly IEntitySystemManager _entSysManager = default!;
|
|
||||||
|
|
||||||
public string Command => "renamestation";
|
|
||||||
|
|
||||||
public string Description => "Renames the given station";
|
|
||||||
|
|
||||||
public string Help => "renamestation <station id> <name>";
|
|
||||||
|
|
||||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
|
||||||
{
|
|
||||||
if (args.Length != 2)
|
|
||||||
{
|
|
||||||
shell.WriteError(Loc.GetString("shell-wrong-arguments-number"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var stationSystem = _entSysManager.GetEntitySystem<StationSystem>();
|
|
||||||
|
|
||||||
if (!EntityUid.TryParse(args[0], out var station) || !_entityManager.HasComponent<StationDataComponent>(station))
|
|
||||||
{
|
|
||||||
shell.WriteError(Loc.GetString("shell-argument-station-id-invalid", ("index", 1)));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
stationSystem.RenameStation(station, args[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CompletionResult GetCompletion(IConsoleShell shell, string[] args)
|
|
||||||
{
|
|
||||||
if (args.Length == 1)
|
|
||||||
{
|
|
||||||
var options = ContentCompletionHelper.StationIds(_entityManager);
|
|
||||||
return CompletionResult.FromHintOptions(options, "<station id>");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args.Length == 2)
|
|
||||||
{
|
|
||||||
return CompletionResult.FromHint("<name>");
|
|
||||||
}
|
|
||||||
|
|
||||||
return CompletionResult.Empty;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,113 +0,0 @@
|
|||||||
using Content.Shared.Administration;
|
|
||||||
using Content.Shared.Tag;
|
|
||||||
using Robust.Shared.Console;
|
|
||||||
|
|
||||||
namespace Content.Server.Administration.Commands
|
|
||||||
{
|
|
||||||
[AdminCommand(AdminFlags.Debug)]
|
|
||||||
public sealed class AddTagCommand : LocalizedCommands
|
|
||||||
{
|
|
||||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
|
||||||
|
|
||||||
public override string Command => "addtag";
|
|
||||||
public override string Description => Loc.GetString("addtag-command-description");
|
|
||||||
public override string Help => Loc.GetString("addtag-command-help");
|
|
||||||
|
|
||||||
public override void Execute(IConsoleShell shell, string argStr, string[] args)
|
|
||||||
{
|
|
||||||
if (args.Length != 2)
|
|
||||||
{
|
|
||||||
shell.WriteError(Loc.GetString("shell-wrong-arguments-number"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!EntityUid.TryParse(args[0], out var entityUid))
|
|
||||||
{
|
|
||||||
shell.WriteError(Loc.GetString("shell-entity-uid-must-be-number"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_entityManager.TrySystem(out TagSystem? tagSystem))
|
|
||||||
return;
|
|
||||||
_entityManager.EnsureComponent<TagComponent>(entityUid);
|
|
||||||
|
|
||||||
if (tagSystem.TryAddTag(entityUid, args[1]))
|
|
||||||
{
|
|
||||||
shell.WriteLine(Loc.GetString("addtag-command-success", ("tag", args[1]), ("target", entityUid)));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
shell.WriteError(Loc.GetString("addtag-command-fail", ("tag", args[1]), ("target", entityUid)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override CompletionResult GetCompletion(IConsoleShell shell, string[] args)
|
|
||||||
{
|
|
||||||
if (args.Length == 1)
|
|
||||||
{
|
|
||||||
return CompletionResult.FromHint(Loc.GetString("shell-argument-uid"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args.Length == 2)
|
|
||||||
{
|
|
||||||
return CompletionResult.FromHintOptions(CompletionHelper.PrototypeIDs<TagPrototype>(),
|
|
||||||
Loc.GetString("tag-command-arg-tag"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return CompletionResult.Empty;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[AdminCommand(AdminFlags.Debug)]
|
|
||||||
public sealed class RemoveTagCommand : LocalizedCommands
|
|
||||||
{
|
|
||||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
|
||||||
|
|
||||||
public override string Command => "removetag";
|
|
||||||
public override string Description => Loc.GetString("removetag-command-description");
|
|
||||||
public override string Help => Loc.GetString("removetag-command-help");
|
|
||||||
|
|
||||||
public override void Execute(IConsoleShell shell, string argStr, string[] args)
|
|
||||||
{
|
|
||||||
if (args.Length != 2)
|
|
||||||
{
|
|
||||||
shell.WriteError(Loc.GetString("shell-wrong-arguments-number"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!EntityUid.TryParse(args[0], out var entityUid))
|
|
||||||
{
|
|
||||||
shell.WriteError(Loc.GetString("shell-entity-uid-must-be-number"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_entityManager.TrySystem(out TagSystem? tagSystem))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (tagSystem.RemoveTag(entityUid, args[1]))
|
|
||||||
{
|
|
||||||
shell.WriteLine(Loc.GetString("removetag-command-success", ("tag", args[1]), ("target", entityUid)));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
shell.WriteError(Loc.GetString("removetag-command-fail", ("tag", args[1]), ("target", entityUid)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override CompletionResult GetCompletion(IConsoleShell shell, string[] args)
|
|
||||||
{
|
|
||||||
if (args.Length == 1)
|
|
||||||
{
|
|
||||||
return CompletionResult.FromHint(Loc.GetString("shell-argument-uid"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args.Length == 2&& EntityUid.TryParse(args[0], out var entityUid) && _entityManager.TryGetComponent(entityUid, out TagComponent? tagComponent))
|
|
||||||
{
|
|
||||||
return CompletionResult.FromHintOptions(tagComponent.Tags,
|
|
||||||
Loc.GetString("tag-command-arg-tag"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return CompletionResult.Empty;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -12,7 +13,11 @@ using Robust.Shared.Configuration;
|
|||||||
using Robust.Shared.Console;
|
using Robust.Shared.Console;
|
||||||
using Robust.Shared.ContentPack;
|
using Robust.Shared.ContentPack;
|
||||||
using Robust.Shared.Enums;
|
using Robust.Shared.Enums;
|
||||||
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Network;
|
using Robust.Shared.Network;
|
||||||
|
using Robust.Shared.Players;
|
||||||
|
using Robust.Shared.Toolshed;
|
||||||
|
using Robust.Shared.Toolshed.Errors;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
|
|
||||||
@@ -28,6 +33,7 @@ namespace Content.Server.Administration.Managers
|
|||||||
[Dependency] private readonly IResourceManager _res = default!;
|
[Dependency] private readonly IResourceManager _res = default!;
|
||||||
[Dependency] private readonly IServerConsoleHost _consoleHost = default!;
|
[Dependency] private readonly IServerConsoleHost _consoleHost = default!;
|
||||||
[Dependency] private readonly IChatManager _chat = default!;
|
[Dependency] private readonly IChatManager _chat = default!;
|
||||||
|
[Dependency] private readonly ToolshedManager _toolshed = default!;
|
||||||
|
|
||||||
private readonly Dictionary<IPlayerSession, AdminReg> _admins = new();
|
private readonly Dictionary<IPlayerSession, AdminReg> _admins = new();
|
||||||
private readonly HashSet<NetUserId> _promotedPlayers = new();
|
private readonly HashSet<NetUserId> _promotedPlayers = new();
|
||||||
@@ -41,6 +47,7 @@ namespace Content.Server.Administration.Managers
|
|||||||
public IEnumerable<IPlayerSession> AllAdmins => _admins.Select(p => p.Key);
|
public IEnumerable<IPlayerSession> AllAdmins => _admins.Select(p => p.Key);
|
||||||
|
|
||||||
private readonly AdminCommandPermissions _commandPermissions = new();
|
private readonly AdminCommandPermissions _commandPermissions = new();
|
||||||
|
private readonly AdminCommandPermissions _toolshedCommandPermissions = new();
|
||||||
|
|
||||||
public bool IsAdmin(IPlayerSession session, bool includeDeAdmin = false)
|
public bool IsAdmin(IPlayerSession session, bool includeDeAdmin = false)
|
||||||
{
|
{
|
||||||
@@ -196,11 +203,37 @@ namespace Content.Server.Administration.Managers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (var spec in _toolshed.AllCommands())
|
||||||
|
{
|
||||||
|
var (isAvail, flagsReq) = GetRequiredFlag(spec.Cmd);
|
||||||
|
|
||||||
|
if (!isAvail)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flagsReq.Length != 0)
|
||||||
|
{
|
||||||
|
_toolshedCommandPermissions.AdminCommands.TryAdd(spec.Cmd.Name, flagsReq);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_toolshedCommandPermissions.AnyCommands.Add(spec.Cmd.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Load flags for engine commands, since those don't have the attributes.
|
// Load flags for engine commands, since those don't have the attributes.
|
||||||
if (_res.TryContentFileRead(new ResPath("/engineCommandPerms.yml"), out var efs))
|
if (_res.TryContentFileRead(new ResPath("/engineCommandPerms.yml"), out var efs))
|
||||||
{
|
{
|
||||||
_commandPermissions.LoadPermissionsFromStream(efs);
|
_commandPermissions.LoadPermissionsFromStream(efs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_res.TryContentFileRead(new ResPath("/toolshedEngineCommandPerms.yml"), out var toolshedPerms))
|
||||||
|
{
|
||||||
|
_toolshedCommandPermissions.LoadPermissionsFromStream(toolshedPerms);
|
||||||
|
}
|
||||||
|
|
||||||
|
_toolshed.ActivePermissionController = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PromoteHost(IPlayerSession player)
|
public void PromoteHost(IPlayerSession player)
|
||||||
@@ -366,6 +399,26 @@ namespace Content.Server.Administration.Managers
|
|||||||
return Equals(addr, System.Net.IPAddress.Loopback) || Equals(addr, System.Net.IPAddress.IPv6Loopback);
|
return Equals(addr, System.Net.IPAddress.Loopback) || Equals(addr, System.Net.IPAddress.IPv6Loopback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool TryGetCommandFlags(CommandSpec command, out AdminFlags[]? flags)
|
||||||
|
{
|
||||||
|
var cmdName = command.Cmd.Name;
|
||||||
|
|
||||||
|
if (_toolshedCommandPermissions.AnyCommands.Contains(cmdName))
|
||||||
|
{
|
||||||
|
// Anybody can use this command.
|
||||||
|
flags = null;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_toolshedCommandPermissions.AdminCommands.TryGetValue(cmdName, out flags))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
flags = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public bool CanCommand(IPlayerSession session, string cmdName)
|
public bool CanCommand(IPlayerSession session, string cmdName)
|
||||||
{
|
{
|
||||||
if (_commandPermissions.AnyCommands.Contains(cmdName))
|
if (_commandPermissions.AnyCommands.Contains(cmdName))
|
||||||
@@ -398,7 +451,51 @@ namespace Content.Server.Administration.Managers
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static (bool isAvail, AdminFlags[] flagsReq) GetRequiredFlag(IConsoleCommand cmd)
|
public bool CheckInvokable(CommandSpec command, ICommonSession? user, out IConError? error)
|
||||||
|
{
|
||||||
|
if (user is null)
|
||||||
|
{
|
||||||
|
error = null;
|
||||||
|
return true; // Server console.
|
||||||
|
}
|
||||||
|
|
||||||
|
var name = command.Cmd.Name;
|
||||||
|
if (!TryGetCommandFlags(command, out var flags))
|
||||||
|
{
|
||||||
|
// Command is missing permissions.
|
||||||
|
error = new CommandPermissionsUnassignedError(command);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags is null)
|
||||||
|
{
|
||||||
|
// Anyone can execute this.
|
||||||
|
error = null;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var data = GetAdminData((IPlayerSession)user);
|
||||||
|
if (data == null)
|
||||||
|
{
|
||||||
|
// Player isn't an admin.
|
||||||
|
error = new NoPermissionError(command);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var flag in flags)
|
||||||
|
{
|
||||||
|
if (data.HasFlag(flag))
|
||||||
|
{
|
||||||
|
error = null;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
error = new NoPermissionError(command);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static (bool isAvail, AdminFlags[] flagsReq) GetRequiredFlag(object cmd)
|
||||||
{
|
{
|
||||||
MemberInfo type = cmd.GetType();
|
MemberInfo type = cmd.GetType();
|
||||||
|
|
||||||
@@ -472,3 +569,28 @@ namespace Content.Server.Administration.Managers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public record struct CommandPermissionsUnassignedError(CommandSpec Command) : IConError
|
||||||
|
{
|
||||||
|
public FormattedMessage DescribeInner()
|
||||||
|
{
|
||||||
|
return FormattedMessage.FromMarkup($"The command {Command.FullName()} is missing permission flags and cannot be executed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public string? Expression { get; set; }
|
||||||
|
public Vector2i? IssueSpan { get; set; }
|
||||||
|
public StackTrace? Trace { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public record struct NoPermissionError(CommandSpec Command) : IConError
|
||||||
|
{
|
||||||
|
public FormattedMessage DescribeInner()
|
||||||
|
{
|
||||||
|
return FormattedMessage.FromMarkup($"You do not have permission to execute {Command.FullName()}");
|
||||||
|
}
|
||||||
|
|
||||||
|
public string? Expression { get; set; }
|
||||||
|
public Vector2i? IssueSpan { get; set; }
|
||||||
|
public StackTrace? Trace { get; set; }
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Content.Shared.Administration;
|
using Content.Shared.Administration;
|
||||||
using Content.Shared.Administration.Managers;
|
using Content.Shared.Administration.Managers;
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
|
using Robust.Shared.Toolshed;
|
||||||
|
|
||||||
|
|
||||||
namespace Content.Server.Administration.Managers
|
namespace Content.Server.Administration.Managers
|
||||||
@@ -87,5 +88,7 @@ namespace Content.Server.Administration.Managers
|
|||||||
void Initialize();
|
void Initialize();
|
||||||
|
|
||||||
void PromoteHost(IPlayerSession player);
|
void PromoteHost(IPlayerSession player);
|
||||||
|
|
||||||
|
bool TryGetCommandFlags(CommandSpec command, out AdminFlags[]? flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ public sealed partial class AdminVerbSystem
|
|||||||
Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/rejuvenate.png")),
|
Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/rejuvenate.png")),
|
||||||
Act = () =>
|
Act = () =>
|
||||||
{
|
{
|
||||||
RejuvenateCommand.PerformRejuvenate(args.Target);
|
_rejuvenate.PerformRejuvenate(args.Target);
|
||||||
},
|
},
|
||||||
Impact = LogImpact.Extreme,
|
Impact = LogImpact.Extreme,
|
||||||
Message = Loc.GetString("admin-trick-rejuvenate-description"),
|
Message = Loc.GetString("admin-trick-rejuvenate-description"),
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System.Linq;
|
||||||
using Content.Server.Administration.Commands;
|
using Content.Server.Administration.Commands;
|
||||||
using Content.Server.Administration.Logs;
|
using Content.Server.Administration.Logs;
|
||||||
using Content.Server.Administration.Managers;
|
using Content.Server.Administration.Managers;
|
||||||
@@ -31,6 +32,7 @@ using Robust.Shared.Map;
|
|||||||
using Robust.Shared.Map.Components;
|
using Robust.Shared.Map.Components;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
|
using Robust.Shared.Toolshed;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
using static Content.Shared.Configurable.ConfigurationComponent;
|
using static Content.Shared.Configurable.ConfigurationComponent;
|
||||||
|
|
||||||
@@ -55,6 +57,8 @@ namespace Content.Server.Administration.Systems
|
|||||||
[Dependency] private readonly PrayerSystem _prayerSystem = default!;
|
[Dependency] private readonly PrayerSystem _prayerSystem = default!;
|
||||||
[Dependency] private readonly EuiManager _eui = default!;
|
[Dependency] private readonly EuiManager _eui = default!;
|
||||||
[Dependency] private readonly MindSystem _mindSystem = default!;
|
[Dependency] private readonly MindSystem _mindSystem = default!;
|
||||||
|
[Dependency] private readonly ToolshedManager _toolshed = default!;
|
||||||
|
[Dependency] private readonly RejuvenateSystem _rejuvenate = default!;
|
||||||
|
|
||||||
private readonly Dictionary<IPlayerSession, EditSolutionsEui> _openSolutionUis = new();
|
private readonly Dictionary<IPlayerSession, EditSolutionsEui> _openSolutionUis = new();
|
||||||
|
|
||||||
@@ -78,6 +82,14 @@ namespace Content.Server.Administration.Systems
|
|||||||
|
|
||||||
if (_adminManager.IsAdmin(player))
|
if (_adminManager.IsAdmin(player))
|
||||||
{
|
{
|
||||||
|
Verb mark = new();
|
||||||
|
mark.Text = Loc.GetString("toolshed-verb-mark");
|
||||||
|
mark.Message = Loc.GetString("toolshed-verb-mark-description");
|
||||||
|
mark.Category = VerbCategory.Admin;
|
||||||
|
mark.Act = () => _toolshed.InvokeCommand(player, "=> $marked", Enumerable.Repeat(args.Target, 1), out _);
|
||||||
|
mark.Impact = LogImpact.Low;
|
||||||
|
args.Verbs.Add(mark);
|
||||||
|
|
||||||
if (TryComp(args.Target, out ActorComponent? targetActor))
|
if (TryComp(args.Target, out ActorComponent? targetActor))
|
||||||
{
|
{
|
||||||
// AdminHelp
|
// AdminHelp
|
||||||
@@ -188,8 +200,6 @@ namespace Content.Server.Administration.Systems
|
|||||||
Category = VerbCategory.Admin,
|
Category = VerbCategory.Admin,
|
||||||
Act = () =>
|
Act = () =>
|
||||||
{
|
{
|
||||||
if (!TryComp<ActorComponent>(args.Target, out var actor)) return;
|
|
||||||
|
|
||||||
_console.ExecuteCommand(player, $"respawn {actor.PlayerSession.Name}");
|
_console.ExecuteCommand(player, $"respawn {actor.PlayerSession.Name}");
|
||||||
},
|
},
|
||||||
ConfirmationPopup = true,
|
ConfirmationPopup = true,
|
||||||
@@ -229,7 +239,7 @@ namespace Content.Server.Administration.Systems
|
|||||||
Text = Loc.GetString("rejuvenate-verb-get-data-text"),
|
Text = Loc.GetString("rejuvenate-verb-get-data-text"),
|
||||||
Category = VerbCategory.Debug,
|
Category = VerbCategory.Debug,
|
||||||
Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/rejuvenate.svg.192dpi.png")),
|
Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/rejuvenate.svg.192dpi.png")),
|
||||||
Act = () => RejuvenateCommand.PerformRejuvenate(args.Target),
|
Act = () => _rejuvenate.PerformRejuvenate(args.Target),
|
||||||
Impact = LogImpact.Medium
|
Impact = LogImpact.Medium
|
||||||
};
|
};
|
||||||
args.Verbs.Add(verb);
|
args.Verbs.Add(verb);
|
||||||
@@ -247,11 +257,11 @@ namespace Content.Server.Administration.Systems
|
|||||||
Act = () =>
|
Act = () =>
|
||||||
{
|
{
|
||||||
MakeSentientCommand.MakeSentient(args.Target, EntityManager);
|
MakeSentientCommand.MakeSentient(args.Target, EntityManager);
|
||||||
|
|
||||||
var mind = player.ContentData()?.Mind;
|
var mind = player.ContentData()?.Mind;
|
||||||
if (mind == null)
|
if (mind == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_mindSystem.TransferTo(mind, args.Target, ghostCheckOverride: true);
|
_mindSystem.TransferTo(mind, args.Target, ghostCheckOverride: true);
|
||||||
},
|
},
|
||||||
Impact = LogImpact.High,
|
Impact = LogImpact.High,
|
||||||
|
|||||||
11
Content.Server/Administration/Systems/RejuvenateSystem.cs
Normal file
11
Content.Server/Administration/Systems/RejuvenateSystem.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
using Content.Shared.Rejuvenate;
|
||||||
|
|
||||||
|
namespace Content.Server.Administration.Systems;
|
||||||
|
|
||||||
|
public sealed class RejuvenateSystem : EntitySystem
|
||||||
|
{
|
||||||
|
public void PerformRejuvenate(EntityUid target)
|
||||||
|
{
|
||||||
|
RaiseLocalEvent(target, new RejuvenateEvent());
|
||||||
|
}
|
||||||
|
}
|
||||||
24
Content.Server/Administration/Toolshed/AdminsCommand.cs
Normal file
24
Content.Server/Administration/Toolshed/AdminsCommand.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
using Content.Server.Administration.Managers;
|
||||||
|
using Content.Shared.Administration;
|
||||||
|
using Robust.Server.Player;
|
||||||
|
using Robust.Shared.Toolshed;
|
||||||
|
|
||||||
|
namespace Content.Server.Administration.Toolshed;
|
||||||
|
|
||||||
|
[ToolshedCommand, AdminCommand(AdminFlags.Admin)]
|
||||||
|
public sealed class AdminsCommand : ToolshedCommand
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IAdminManager _admin = default!;
|
||||||
|
|
||||||
|
[CommandImplementation("active")]
|
||||||
|
public IEnumerable<IPlayerSession> Active()
|
||||||
|
{
|
||||||
|
return _admin.ActiveAdmins;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandImplementation("all")]
|
||||||
|
public IEnumerable<IPlayerSession> All()
|
||||||
|
{
|
||||||
|
return _admin.AllAdmins;
|
||||||
|
}
|
||||||
|
}
|
||||||
16
Content.Server/Administration/Toolshed/MarkedCommand.cs
Normal file
16
Content.Server/Administration/Toolshed/MarkedCommand.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
using Content.Shared.Administration;
|
||||||
|
using Robust.Shared.Toolshed;
|
||||||
|
|
||||||
|
namespace Content.Server.Administration.Toolshed;
|
||||||
|
|
||||||
|
[ToolshedCommand, AnyCommand]
|
||||||
|
public sealed class MarkedCommand : ToolshedCommand
|
||||||
|
{
|
||||||
|
[CommandImplementation]
|
||||||
|
public IEnumerable<EntityUid> Marked([CommandInvocationContext] IInvocationContext ctx)
|
||||||
|
{
|
||||||
|
var res = (IEnumerable<EntityUid>?)ctx.ReadVar("marked");
|
||||||
|
res ??= Array.Empty<EntityUid>();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
22
Content.Server/Administration/Toolshed/RejuvenateCommand.cs
Normal file
22
Content.Server/Administration/Toolshed/RejuvenateCommand.cs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
using Content.Server.Administration.Systems;
|
||||||
|
using Content.Shared.Administration;
|
||||||
|
using Robust.Shared.Toolshed;
|
||||||
|
|
||||||
|
namespace Content.Server.Administration.Toolshed;
|
||||||
|
|
||||||
|
[ToolshedCommand, AdminCommand(AdminFlags.Admin)]
|
||||||
|
public sealed class RejuvenateCommand : ToolshedCommand
|
||||||
|
{
|
||||||
|
private RejuvenateSystem? _rejuvenate;
|
||||||
|
[CommandImplementation]
|
||||||
|
public IEnumerable<EntityUid> Rejuvenate([PipedArgument] IEnumerable<EntityUid> input)
|
||||||
|
{
|
||||||
|
_rejuvenate ??= GetSys<RejuvenateSystem>();
|
||||||
|
|
||||||
|
foreach (var i in input)
|
||||||
|
{
|
||||||
|
_rejuvenate.PerformRejuvenate(i);
|
||||||
|
yield return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
49
Content.Server/Administration/Toolshed/SolutionCommand.cs
Normal file
49
Content.Server/Administration/Toolshed/SolutionCommand.cs
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using Content.Server.Chemistry.EntitySystems;
|
||||||
|
using Content.Shared.Administration;
|
||||||
|
using Content.Shared.Chemistry.Components;
|
||||||
|
using Robust.Shared.Toolshed;
|
||||||
|
using Robust.Shared.Toolshed.Syntax;
|
||||||
|
|
||||||
|
namespace Content.Server.Administration.Toolshed;
|
||||||
|
|
||||||
|
[ToolshedCommand, AdminCommand(AdminFlags.Debug)]
|
||||||
|
public sealed class SolutionCommand : ToolshedCommand
|
||||||
|
{
|
||||||
|
private SolutionContainerSystem? _solutionContainer;
|
||||||
|
|
||||||
|
[CommandImplementation("get")]
|
||||||
|
public SolutionRef? Get(
|
||||||
|
[CommandInvocationContext] IInvocationContext ctx,
|
||||||
|
[PipedArgument] EntityUid input,
|
||||||
|
[CommandArgument] ValueRef<string> name
|
||||||
|
)
|
||||||
|
{
|
||||||
|
_solutionContainer ??= GetSys<SolutionContainerSystem>();
|
||||||
|
|
||||||
|
_solutionContainer.TryGetSolution(input, name.Evaluate(ctx)!, out var solution);
|
||||||
|
|
||||||
|
if (solution is not null)
|
||||||
|
return new SolutionRef(input, solution);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandImplementation("get")]
|
||||||
|
public IEnumerable<SolutionRef> Get(
|
||||||
|
[CommandInvocationContext] IInvocationContext ctx,
|
||||||
|
[PipedArgument] IEnumerable<EntityUid> input,
|
||||||
|
[CommandArgument] ValueRef<string> name
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return input.Select(x => Get(ctx, x, name)).Where(x => x is not null).Cast<SolutionRef>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly record struct SolutionRef(EntityUid Owner, Solution Solution)
|
||||||
|
{
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"{Owner} {Solution}";
|
||||||
|
}
|
||||||
|
}
|
||||||
106
Content.Server/Administration/Toolshed/TagCommand.cs
Normal file
106
Content.Server/Administration/Toolshed/TagCommand.cs
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using Content.Shared.Administration;
|
||||||
|
using Content.Shared.Tag;
|
||||||
|
using Robust.Shared.Toolshed;
|
||||||
|
using Robust.Shared.Toolshed.Syntax;
|
||||||
|
using Robust.Shared.Toolshed.TypeParsers;
|
||||||
|
|
||||||
|
namespace Content.Server.Administration.Toolshed;
|
||||||
|
|
||||||
|
[ToolshedCommand, AdminCommand(AdminFlags.Debug)]
|
||||||
|
public sealed class TagCommand : ToolshedCommand
|
||||||
|
{
|
||||||
|
private TagSystem? _tag;
|
||||||
|
|
||||||
|
[CommandImplementation("list")]
|
||||||
|
public IEnumerable<string> List([PipedArgument] IEnumerable<EntityUid> ent)
|
||||||
|
{
|
||||||
|
return ent.SelectMany(x =>
|
||||||
|
{
|
||||||
|
if (TryComp<TagComponent>(x, out var tags))
|
||||||
|
// Note: Cast is required for C# to figure out the type signature.
|
||||||
|
return (IEnumerable<string>)tags.Tags;
|
||||||
|
return Array.Empty<string>();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandImplementation("add")]
|
||||||
|
public EntityUid Add(
|
||||||
|
[CommandInvocationContext] IInvocationContext ctx,
|
||||||
|
[PipedArgument] EntityUid input,
|
||||||
|
[CommandArgument] ValueRef<string, Prototype<TagPrototype>> @ref
|
||||||
|
)
|
||||||
|
{
|
||||||
|
_tag ??= GetSys<TagSystem>();
|
||||||
|
_tag.AddTag(input, @ref.Evaluate(ctx)!);
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandImplementation("add")]
|
||||||
|
public IEnumerable<EntityUid> Add(
|
||||||
|
[CommandInvocationContext] IInvocationContext ctx,
|
||||||
|
[PipedArgument] IEnumerable<EntityUid> input,
|
||||||
|
[CommandArgument] ValueRef<string, Prototype<TagPrototype>> @ref
|
||||||
|
)
|
||||||
|
=> input.Select(x => Add(ctx, x, @ref));
|
||||||
|
|
||||||
|
[CommandImplementation("rm")]
|
||||||
|
public EntityUid Rm(
|
||||||
|
[CommandInvocationContext] IInvocationContext ctx,
|
||||||
|
[PipedArgument] EntityUid input,
|
||||||
|
[CommandArgument] ValueRef<string, Prototype<TagPrototype>> @ref
|
||||||
|
)
|
||||||
|
{
|
||||||
|
_tag ??= GetSys<TagSystem>();
|
||||||
|
_tag.RemoveTag(input, @ref.Evaluate(ctx)!);
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandImplementation("rm")]
|
||||||
|
public IEnumerable<EntityUid> Rm(
|
||||||
|
[CommandInvocationContext] IInvocationContext ctx,
|
||||||
|
[PipedArgument] IEnumerable<EntityUid> input,
|
||||||
|
[CommandArgument] ValueRef<string, Prototype<TagPrototype>> @ref
|
||||||
|
)
|
||||||
|
=> input.Select(x => Rm(ctx, x, @ref));
|
||||||
|
|
||||||
|
[CommandImplementation("addmany")]
|
||||||
|
public EntityUid AddMany(
|
||||||
|
[CommandInvocationContext] IInvocationContext ctx,
|
||||||
|
[PipedArgument] EntityUid input,
|
||||||
|
[CommandArgument] ValueRef<IEnumerable<string>, IEnumerable<string>> @ref
|
||||||
|
)
|
||||||
|
{
|
||||||
|
_tag ??= GetSys<TagSystem>();
|
||||||
|
_tag.AddTags(input, @ref.Evaluate(ctx)!);
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandImplementation("addmany")]
|
||||||
|
public IEnumerable<EntityUid> AddMany(
|
||||||
|
[CommandInvocationContext] IInvocationContext ctx,
|
||||||
|
[PipedArgument] IEnumerable<EntityUid> input,
|
||||||
|
[CommandArgument] ValueRef<IEnumerable<string>, IEnumerable<string>> @ref
|
||||||
|
)
|
||||||
|
=> input.Select(x => AddMany(ctx, x, @ref));
|
||||||
|
|
||||||
|
[CommandImplementation("rmmany")]
|
||||||
|
public EntityUid RmMany(
|
||||||
|
[CommandInvocationContext] IInvocationContext ctx,
|
||||||
|
[PipedArgument] EntityUid input,
|
||||||
|
[CommandArgument] ValueRef<IEnumerable<string>, IEnumerable<string>> @ref
|
||||||
|
)
|
||||||
|
{
|
||||||
|
_tag ??= GetSys<TagSystem>();
|
||||||
|
_tag.RemoveTags(input, @ref.Evaluate(ctx)!);
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandImplementation("rmmany")]
|
||||||
|
public IEnumerable<EntityUid> RmMany(
|
||||||
|
[CommandInvocationContext] IInvocationContext ctx,
|
||||||
|
[PipedArgument] IEnumerable<EntityUid> input,
|
||||||
|
[CommandArgument] ValueRef<IEnumerable<string>, IEnumerable<string>> @ref
|
||||||
|
)
|
||||||
|
=> input.Select(x => RmMany(ctx, x, @ref));
|
||||||
|
}
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
using System.Linq;
|
|
||||||
using Content.Server.Administration;
|
|
||||||
using Content.Server.EUI;
|
|
||||||
using Content.Shared.Administration;
|
|
||||||
using Content.Shared.Bql;
|
|
||||||
using Content.Shared.Eui;
|
|
||||||
using Robust.Server.Bql;
|
|
||||||
using Robust.Server.Player;
|
|
||||||
using Robust.Shared.Console;
|
|
||||||
|
|
||||||
namespace Content.Server.Bql;
|
|
||||||
|
|
||||||
[AdminCommand(AdminFlags.Query)]
|
|
||||||
public sealed class BqlSelectCommand : LocalizedCommands
|
|
||||||
{
|
|
||||||
[Dependency] private readonly IBqlQueryManager _bql = default!;
|
|
||||||
[Dependency] private readonly EuiManager _euiManager = default!;
|
|
||||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
|
||||||
|
|
||||||
public override string Command => "bql_select";
|
|
||||||
|
|
||||||
public override void Execute(IConsoleShell shell, string argStr, string[] args)
|
|
||||||
{
|
|
||||||
if (shell.Player == null)
|
|
||||||
{
|
|
||||||
shell.WriteError(LocalizationManager.GetString("cmd-bql_select-err-server-shell"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var (entities, rest) = _bql.SimpleParseAndExecute(argStr["bql_select".Length..]);
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(rest))
|
|
||||||
shell.WriteLine(LocalizationManager.GetString("cmd-bql_select-err-rest", ("rest", rest)));
|
|
||||||
|
|
||||||
var ui = new BqlResultsEui(
|
|
||||||
entities.Select(e => (_entityManager.GetComponent<MetaDataComponent>(e).EntityName, e)).ToArray()
|
|
||||||
);
|
|
||||||
_euiManager.OpenEui(ui, (IPlayerSession) shell.Player);
|
|
||||||
_euiManager.QueueStateUpdate(ui);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal sealed class BqlResultsEui : BaseEui
|
|
||||||
{
|
|
||||||
private readonly (string name, EntityUid entity)[] _entities;
|
|
||||||
|
|
||||||
public BqlResultsEui((string name, EntityUid entity)[] entities)
|
|
||||||
{
|
|
||||||
_entities = entities;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override EuiStateBase GetNewState()
|
|
||||||
{
|
|
||||||
return new BqlResultsEuiState(_entities);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,137 +0,0 @@
|
|||||||
using System.Linq;
|
|
||||||
using Content.Server.Chemistry.Components.SolutionManager;
|
|
||||||
using Content.Server.Mind;
|
|
||||||
using Content.Server.Mind.Components;
|
|
||||||
using Content.Server.Power.Components;
|
|
||||||
using Content.Shared.Tag;
|
|
||||||
using Robust.Server.Bql;
|
|
||||||
|
|
||||||
namespace Content.Server.Bql
|
|
||||||
{
|
|
||||||
public sealed class QuerySelectors
|
|
||||||
{
|
|
||||||
[RegisterBqlQuerySelector]
|
|
||||||
public sealed class MindfulQuerySelector : BqlQuerySelector
|
|
||||||
{
|
|
||||||
public override string Token => "mindful";
|
|
||||||
|
|
||||||
public override QuerySelectorArgument[] Arguments => Array.Empty<QuerySelectorArgument>();
|
|
||||||
|
|
||||||
public override IEnumerable<EntityUid> DoSelection(IEnumerable<EntityUid> input,
|
|
||||||
IReadOnlyList<object> arguments, bool isInverted, IEntityManager entityManager)
|
|
||||||
{
|
|
||||||
return input.Where(e =>
|
|
||||||
{
|
|
||||||
if (entityManager.TryGetComponent<MindContainerComponent>(e, out var mind))
|
|
||||||
return (mind.Mind?.VisitingEntity == e) ^ isInverted;
|
|
||||||
|
|
||||||
return isInverted;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public override IEnumerable<EntityUid> DoInitialSelection(IReadOnlyList<object> arguments, bool isInverted, IEntityManager entityManager)
|
|
||||||
{
|
|
||||||
|
|
||||||
return DoSelection(
|
|
||||||
entityManager.EntityQuery<MindContainerComponent>().Select(x => x.Owner),
|
|
||||||
arguments, isInverted, entityManager);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[RegisterBqlQuerySelector]
|
|
||||||
public sealed class TaggedQuerySelector : BqlQuerySelector
|
|
||||||
{
|
|
||||||
public override string Token => "tagged";
|
|
||||||
|
|
||||||
public override QuerySelectorArgument[] Arguments => new [] { QuerySelectorArgument.String };
|
|
||||||
|
|
||||||
public override IEnumerable<EntityUid> DoSelection(IEnumerable<EntityUid> input, IReadOnlyList<object> arguments, bool isInverted, IEntityManager entityManager)
|
|
||||||
{
|
|
||||||
return input.Where(e =>
|
|
||||||
(entityManager.TryGetComponent<TagComponent>(e, out var tag) &&
|
|
||||||
tag.Tags.Contains((string) arguments[0])) ^ isInverted);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override IEnumerable<EntityUid> DoInitialSelection(IReadOnlyList<object> arguments, bool isInverted, IEntityManager entityManager)
|
|
||||||
{
|
|
||||||
return DoSelection(entityManager.EntityQuery<TagComponent>().Select(x => x.Owner), arguments,
|
|
||||||
isInverted, entityManager);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[RegisterBqlQuerySelector]
|
|
||||||
public sealed class AliveQuerySelector : BqlQuerySelector
|
|
||||||
{
|
|
||||||
public override string Token => "alive";
|
|
||||||
|
|
||||||
public override QuerySelectorArgument[] Arguments => Array.Empty<QuerySelectorArgument>();
|
|
||||||
|
|
||||||
public override IEnumerable<EntityUid> DoSelection(IEnumerable<EntityUid> input, IReadOnlyList<object> arguments, bool isInverted, IEntityManager entityManager)
|
|
||||||
{
|
|
||||||
var mindSystem = entityManager.System<MindSystem>();
|
|
||||||
return input.Where(e =>
|
|
||||||
entityManager.TryGetComponent<MindContainerComponent>(e, out var mind)
|
|
||||||
&& mind.Mind != null
|
|
||||||
&& !mindSystem.IsCharacterDeadPhysically(mind.Mind));
|
|
||||||
}
|
|
||||||
|
|
||||||
public override IEnumerable<EntityUid> DoInitialSelection(IReadOnlyList<object> arguments, bool isInverted, IEntityManager entityManager)
|
|
||||||
{
|
|
||||||
return DoSelection(entityManager.EntityQuery<MindContainerComponent>().Select(x => x.Owner), arguments,
|
|
||||||
isInverted, entityManager);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[RegisterBqlQuerySelector]
|
|
||||||
public sealed class HasReagentQuerySelector : BqlQuerySelector
|
|
||||||
{
|
|
||||||
public override string Token => "hasreagent";
|
|
||||||
|
|
||||||
public override QuerySelectorArgument[] Arguments => new [] { QuerySelectorArgument.String };
|
|
||||||
|
|
||||||
public override IEnumerable<EntityUid> DoSelection(IEnumerable<EntityUid> input, IReadOnlyList<object> arguments, bool isInverted, IEntityManager entityManager)
|
|
||||||
{
|
|
||||||
var reagent = (string) arguments[0];
|
|
||||||
return input.Where(e =>
|
|
||||||
{
|
|
||||||
if (entityManager.TryGetComponent<SolutionContainerManagerComponent>(e, out var solutionContainerManagerComponent))
|
|
||||||
{
|
|
||||||
return solutionContainerManagerComponent.Solutions
|
|
||||||
.Any(solution => solution.Value.ContainsReagent(reagent)) ^ isInverted;
|
|
||||||
}
|
|
||||||
|
|
||||||
return isInverted;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public override IEnumerable<EntityUid> DoInitialSelection(IReadOnlyList<object> arguments, bool isInverted, IEntityManager entityManager)
|
|
||||||
{
|
|
||||||
return DoSelection(entityManager.EntityQuery<SolutionContainerManagerComponent>().Select(x => x.Owner), arguments,
|
|
||||||
isInverted, entityManager);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[RegisterBqlQuerySelector]
|
|
||||||
public sealed class ApcPoweredQuerySelector : BqlQuerySelector
|
|
||||||
{
|
|
||||||
public override string Token => "apcpowered";
|
|
||||||
|
|
||||||
public override QuerySelectorArgument[] Arguments => Array.Empty<QuerySelectorArgument>();
|
|
||||||
|
|
||||||
public override IEnumerable<EntityUid> DoSelection(IEnumerable<EntityUid> input, IReadOnlyList<object> arguments, bool isInverted, IEntityManager entityManager)
|
|
||||||
{
|
|
||||||
return input.Where(e =>
|
|
||||||
entityManager.TryGetComponent<ApcPowerReceiverComponent>(e, out var apcPowerReceiver)
|
|
||||||
? apcPowerReceiver.Powered ^ isInverted
|
|
||||||
: isInverted);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override IEnumerable<EntityUid> DoInitialSelection(IReadOnlyList<object> arguments, bool isInverted, IEntityManager entityManager)
|
|
||||||
{
|
|
||||||
return DoSelection(entityManager.EntityQuery<ApcPowerReceiverComponent>().Select(x => x.Owner), arguments,
|
|
||||||
isInverted, entityManager);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -19,18 +19,15 @@ using Content.Server.Preferences.Managers;
|
|||||||
using Content.Server.ServerInfo;
|
using Content.Server.ServerInfo;
|
||||||
using Content.Server.ServerUpdates;
|
using Content.Server.ServerUpdates;
|
||||||
using Content.Server.Voting.Managers;
|
using Content.Server.Voting.Managers;
|
||||||
using Content.Shared.Administration;
|
|
||||||
using Content.Shared.CCVar;
|
using Content.Shared.CCVar;
|
||||||
using Content.Shared.Kitchen;
|
using Content.Shared.Kitchen;
|
||||||
using Robust.Server;
|
using Robust.Server;
|
||||||
using Robust.Server.Bql;
|
|
||||||
using Robust.Shared.Configuration;
|
using Robust.Shared.Configuration;
|
||||||
using Robust.Server.ServerStatus;
|
using Robust.Server.ServerStatus;
|
||||||
using Robust.Shared.ContentPack;
|
using Robust.Shared.ContentPack;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
using Content.Server.Station.Systems;
|
|
||||||
using Content.Shared.Localizations;
|
using Content.Shared.Localizations;
|
||||||
|
|
||||||
namespace Content.Server.Entry
|
namespace Content.Server.Entry
|
||||||
@@ -145,7 +142,6 @@ namespace Content.Server.Entry
|
|||||||
|
|
||||||
IoCManager.Resolve<IGameMapManager>().Initialize();
|
IoCManager.Resolve<IGameMapManager>().Initialize();
|
||||||
IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<GameTicker>().PostInitialize();
|
IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<GameTicker>().PostInitialize();
|
||||||
IoCManager.Resolve<IBqlQueryManager>().DoAutoRegistrations();
|
|
||||||
IoCManager.Resolve<IBanManager>().Initialize();
|
IoCManager.Resolve<IBanManager>().Initialize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ using Content.Server.GhostKick;
|
|||||||
using Content.Server.Info;
|
using Content.Server.Info;
|
||||||
using Content.Server.Maps;
|
using Content.Server.Maps;
|
||||||
using Content.Server.MoMMI;
|
using Content.Server.MoMMI;
|
||||||
|
using Content.Server.NewCon;
|
||||||
using Content.Server.NodeContainer.NodeGroups;
|
using Content.Server.NodeContainer.NodeGroups;
|
||||||
using Content.Server.Objectives;
|
using Content.Server.Objectives;
|
||||||
using Content.Server.Objectives.Interfaces;
|
using Content.Server.Objectives.Interfaces;
|
||||||
@@ -23,6 +24,7 @@ using Content.Server.Worldgen.Tools;
|
|||||||
using Content.Shared.Administration.Logs;
|
using Content.Shared.Administration.Logs;
|
||||||
using Content.Shared.Administration.Managers;
|
using Content.Shared.Administration.Managers;
|
||||||
using Content.Shared.Kitchen;
|
using Content.Shared.Kitchen;
|
||||||
|
using Robust.Shared.Toolshed;
|
||||||
|
|
||||||
namespace Content.Server.IoC
|
namespace Content.Server.IoC
|
||||||
{
|
{
|
||||||
|
|||||||
34
Content.Server/NewCon/Commands/AdminDebug/ACmdCommand.cs
Normal file
34
Content.Server/NewCon/Commands/AdminDebug/ACmdCommand.cs
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
using Content.Server.Administration;
|
||||||
|
using Content.Server.Administration.Managers;
|
||||||
|
using Content.Shared.Administration;
|
||||||
|
using Robust.Server.Player;
|
||||||
|
using Robust.Shared.Toolshed;
|
||||||
|
using Robust.Shared.Toolshed.Syntax;
|
||||||
|
|
||||||
|
namespace Content.Server.NewCon.Commands.AdminDebug;
|
||||||
|
|
||||||
|
[ToolshedCommand, AdminCommand(AdminFlags.Debug)]
|
||||||
|
public sealed class ACmdCommand : ToolshedCommand
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IAdminManager _adminManager = default!;
|
||||||
|
|
||||||
|
[CommandImplementation("perms")]
|
||||||
|
public AdminFlags[]? Perms([PipedArgument] CommandSpec command)
|
||||||
|
{
|
||||||
|
var res = _adminManager.TryGetCommandFlags(command, out var flags);
|
||||||
|
if (res)
|
||||||
|
flags ??= Array.Empty<AdminFlags>();
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandImplementation("caninvoke")]
|
||||||
|
public bool CanInvoke(
|
||||||
|
[CommandInvocationContext] IInvocationContext ctx,
|
||||||
|
[PipedArgument] CommandSpec command,
|
||||||
|
[CommandArgument] ValueRef<IPlayerSession> player
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Deliberately discard the error.
|
||||||
|
return ((IPermissionController) _adminManager).CheckInvokable(command, player.Evaluate(ctx), out var err);
|
||||||
|
}
|
||||||
|
}
|
||||||
62
Content.Server/NewCon/Commands/Verbs/RunVerbAsCommand.cs
Normal file
62
Content.Server/NewCon/Commands/Verbs/RunVerbAsCommand.cs
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using Content.Server.Administration;
|
||||||
|
using Content.Shared.Administration;
|
||||||
|
using Content.Shared.Verbs;
|
||||||
|
using Robust.Shared.Toolshed;
|
||||||
|
using Robust.Shared.Toolshed.Syntax;
|
||||||
|
using Robust.Shared.Toolshed.TypeParsers;
|
||||||
|
|
||||||
|
namespace Content.Server.NewCon.Commands.Verbs;
|
||||||
|
|
||||||
|
[ToolshedCommand, AdminCommand(AdminFlags.Admin)]
|
||||||
|
public sealed class RunVerbAsCommand : ToolshedCommand
|
||||||
|
{
|
||||||
|
private SharedVerbSystem? _verb;
|
||||||
|
|
||||||
|
[CommandImplementation]
|
||||||
|
public IEnumerable<EntityUid> RunVerbAs(
|
||||||
|
[CommandInvocationContext] IInvocationContext ctx,
|
||||||
|
[PipedArgument] IEnumerable<EntityUid> input,
|
||||||
|
[CommandArgument] ValueRef<EntityUid> runner,
|
||||||
|
[CommandArgument] string verb
|
||||||
|
)
|
||||||
|
{
|
||||||
|
_verb ??= GetSys<SharedVerbSystem>();
|
||||||
|
verb = verb.ToLowerInvariant();
|
||||||
|
|
||||||
|
foreach (var i in input)
|
||||||
|
{
|
||||||
|
var runnerEid = runner.Evaluate(ctx);
|
||||||
|
|
||||||
|
|
||||||
|
if (EntityManager.Deleted(runnerEid) && runnerEid != default)
|
||||||
|
ctx.ReportError(new DeadEntity(runnerEid));
|
||||||
|
|
||||||
|
if (ctx.GetErrors().Any())
|
||||||
|
yield break;
|
||||||
|
|
||||||
|
var verbs = _verb.GetLocalVerbs(i, runnerEid, Verb.VerbTypes, true);
|
||||||
|
|
||||||
|
// if the "verb name" is actually a verb-type, try run any verb of that type.
|
||||||
|
var verbType = Verb.VerbTypes.FirstOrDefault(x => x.Name == verb);
|
||||||
|
if (verbType != null)
|
||||||
|
{
|
||||||
|
var verbTy = verbs.FirstOrDefault(v => v.GetType() == verbType);
|
||||||
|
if (verbTy != null)
|
||||||
|
{
|
||||||
|
_verb.ExecuteVerb(verbTy, runnerEid, i, forced: true);
|
||||||
|
yield return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var verbTy in verbs)
|
||||||
|
{
|
||||||
|
if (verbTy.Text.ToLowerInvariant() == verb)
|
||||||
|
{
|
||||||
|
_verb.ExecuteVerb(verbTy, runnerEid, i, forced: true);
|
||||||
|
yield return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
51
Content.Server/NewCon/Commands/VisualizeCommand.cs
Normal file
51
Content.Server/NewCon/Commands/VisualizeCommand.cs
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using Content.Server.Administration;
|
||||||
|
using Content.Server.EUI;
|
||||||
|
using Content.Shared.Administration;
|
||||||
|
using Content.Shared.Bql;
|
||||||
|
using Content.Shared.Eui;
|
||||||
|
using Robust.Server.Player;
|
||||||
|
using Robust.Shared.Toolshed;
|
||||||
|
using Robust.Shared.Toolshed.Errors;
|
||||||
|
|
||||||
|
namespace Content.Server.NewCon.Commands;
|
||||||
|
|
||||||
|
[ToolshedCommand, AdminCommand(AdminFlags.Admin)]
|
||||||
|
public sealed class VisualizeCommand : ToolshedCommand
|
||||||
|
{
|
||||||
|
[Dependency] private readonly EuiManager _euiManager = default!;
|
||||||
|
|
||||||
|
[CommandImplementation]
|
||||||
|
public void VisualizeEntities(
|
||||||
|
[CommandInvocationContext] IInvocationContext ctx,
|
||||||
|
[PipedArgument] IEnumerable<EntityUid> input
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (ctx.Session is null)
|
||||||
|
{
|
||||||
|
ctx.ReportError(new NotForServerConsoleError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var ui = new ToolshedVisualizeEui(
|
||||||
|
input.Select(e => (EntName(e), e)).ToArray()
|
||||||
|
);
|
||||||
|
_euiManager.OpenEui(ui, (IPlayerSession) ctx.Session);
|
||||||
|
_euiManager.QueueStateUpdate(ui);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
internal sealed class ToolshedVisualizeEui : BaseEui
|
||||||
|
{
|
||||||
|
private readonly (string name, EntityUid entity)[] _entities;
|
||||||
|
|
||||||
|
public ToolshedVisualizeEui((string name, EntityUid entity)[] entities)
|
||||||
|
{
|
||||||
|
_entities = entities;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override EuiStateBase GetNewState()
|
||||||
|
{
|
||||||
|
return new ToolshedVisualizeEuiState(_entities);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
129
Content.Server/Station/Commands/JobsCommand.cs
Normal file
129
Content.Server/Station/Commands/JobsCommand.cs
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using Content.Server.Administration;
|
||||||
|
using Content.Server.Station.Systems;
|
||||||
|
using Content.Shared.Administration;
|
||||||
|
using Content.Shared.Roles;
|
||||||
|
using Robust.Shared.Toolshed;
|
||||||
|
using Robust.Shared.Toolshed.Syntax;
|
||||||
|
using Robust.Shared.Toolshed.TypeParsers;
|
||||||
|
|
||||||
|
namespace Content.Server.Station.Commands;
|
||||||
|
|
||||||
|
[ToolshedCommand, AdminCommand(AdminFlags.VarEdit)]
|
||||||
|
public sealed class JobsCommand : ToolshedCommand
|
||||||
|
{
|
||||||
|
private StationJobsSystem? _jobs;
|
||||||
|
|
||||||
|
[CommandImplementation("jobs")]
|
||||||
|
public IEnumerable<JobSlotRef> Jobs([PipedArgument] EntityUid station)
|
||||||
|
{
|
||||||
|
_jobs ??= GetSys<StationJobsSystem>();
|
||||||
|
|
||||||
|
foreach (var (job, _) in _jobs.GetJobs(station))
|
||||||
|
{
|
||||||
|
yield return new JobSlotRef(job, station, _jobs, EntityManager);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandImplementation("jobs")]
|
||||||
|
public IEnumerable<JobSlotRef> Jobs([PipedArgument] IEnumerable<EntityUid> stations)
|
||||||
|
=> stations.SelectMany(Jobs);
|
||||||
|
|
||||||
|
[CommandImplementation("job")]
|
||||||
|
public JobSlotRef Job([PipedArgument] EntityUid station, [CommandArgument] Prototype<JobPrototype> job)
|
||||||
|
{
|
||||||
|
_jobs ??= GetSys<StationJobsSystem>();
|
||||||
|
|
||||||
|
return new JobSlotRef(job.Value.ID, station, _jobs, EntityManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandImplementation("job")]
|
||||||
|
public IEnumerable<JobSlotRef> Job([PipedArgument] IEnumerable<EntityUid> stations, [CommandArgument] Prototype<JobPrototype> job)
|
||||||
|
=> stations.Select(x => Job(x, job));
|
||||||
|
|
||||||
|
[CommandImplementation("isinfinite")]
|
||||||
|
public bool IsInfinite([PipedArgument] JobSlotRef job, [CommandInverted] bool inverted)
|
||||||
|
=> job.Infinite() ^ inverted;
|
||||||
|
|
||||||
|
[CommandImplementation("isinfinite")]
|
||||||
|
public IEnumerable<bool> IsInfinite([PipedArgument] IEnumerable<JobSlotRef> jobs, [CommandInverted] bool inverted)
|
||||||
|
=> jobs.Select(x => IsInfinite(x, inverted));
|
||||||
|
|
||||||
|
[CommandImplementation("adjust")]
|
||||||
|
public JobSlotRef Adjust(
|
||||||
|
[CommandInvocationContext] IInvocationContext ctx,
|
||||||
|
[PipedArgument] JobSlotRef @ref,
|
||||||
|
[CommandArgument] ValueRef<int> by
|
||||||
|
)
|
||||||
|
{
|
||||||
|
_jobs ??= GetSys<StationJobsSystem>();
|
||||||
|
_jobs.TryAdjustJobSlot(@ref.Station, @ref.Job, by.Evaluate(ctx), true, true);
|
||||||
|
return @ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandImplementation("adjust")]
|
||||||
|
public IEnumerable<JobSlotRef> Adjust(
|
||||||
|
[CommandInvocationContext] IInvocationContext ctx,
|
||||||
|
[PipedArgument] IEnumerable<JobSlotRef> @ref,
|
||||||
|
[CommandArgument] ValueRef<int> by
|
||||||
|
)
|
||||||
|
=> @ref.Select(x => Adjust(ctx, x, by));
|
||||||
|
|
||||||
|
|
||||||
|
[CommandImplementation("set")]
|
||||||
|
public JobSlotRef Set(
|
||||||
|
[CommandInvocationContext] IInvocationContext ctx,
|
||||||
|
[PipedArgument] JobSlotRef @ref,
|
||||||
|
[CommandArgument] ValueRef<int> by
|
||||||
|
)
|
||||||
|
{
|
||||||
|
_jobs ??= GetSys<StationJobsSystem>();
|
||||||
|
_jobs.TrySetJobSlot(@ref.Station, @ref.Job, by.Evaluate(ctx), true);
|
||||||
|
return @ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandImplementation("set")]
|
||||||
|
public IEnumerable<JobSlotRef> Set(
|
||||||
|
[CommandInvocationContext] IInvocationContext ctx,
|
||||||
|
[PipedArgument] IEnumerable<JobSlotRef> @ref,
|
||||||
|
[CommandArgument] ValueRef<int> by
|
||||||
|
)
|
||||||
|
=> @ref.Select(x => Set(ctx, x, by));
|
||||||
|
|
||||||
|
[CommandImplementation("amount")]
|
||||||
|
public int Amount(
|
||||||
|
[CommandInvocationContext] IInvocationContext ctx,
|
||||||
|
[PipedArgument] JobSlotRef @ref
|
||||||
|
)
|
||||||
|
{
|
||||||
|
_jobs ??= GetSys<StationJobsSystem>();
|
||||||
|
_jobs.TryGetJobSlot(@ref.Station, @ref.Job, out var slots);
|
||||||
|
return (int)(slots ?? 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandImplementation("amount")]
|
||||||
|
public IEnumerable<int> Amount(
|
||||||
|
[CommandInvocationContext] IInvocationContext ctx,
|
||||||
|
[PipedArgument] IEnumerable<JobSlotRef> @ref
|
||||||
|
)
|
||||||
|
=> @ref.Select(x => Amount(ctx, x));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used for Toolshed queries.
|
||||||
|
public readonly record struct JobSlotRef(string Job, EntityUid Station, StationJobsSystem Jobs, IEntityManager EntityManager)
|
||||||
|
{
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
if (!Jobs.TryGetJobSlot(Station, Job, out var slot))
|
||||||
|
{
|
||||||
|
return $"{EntityManager.ToPrettyString(Station)} job {Job} : (not a slot)";
|
||||||
|
}
|
||||||
|
|
||||||
|
return $"{EntityManager.ToPrettyString(Station)} job {Job} : {slot?.ToString() ?? "infinite"}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Infinite()
|
||||||
|
{
|
||||||
|
return Jobs.TryGetJobSlot(Station, Job, out var slot) && slot is null;
|
||||||
|
}
|
||||||
|
}
|
||||||
126
Content.Server/Station/Commands/StationCommand.cs
Normal file
126
Content.Server/Station/Commands/StationCommand.cs
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
using Content.Server.Administration;
|
||||||
|
using Content.Server.Station.Components;
|
||||||
|
using Content.Server.Station.Systems;
|
||||||
|
using Content.Shared.Administration;
|
||||||
|
using Robust.Shared.Toolshed;
|
||||||
|
using Robust.Shared.Toolshed.Errors;
|
||||||
|
using Robust.Shared.Toolshed.Syntax;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
|
namespace Content.Server.Station.Commands;
|
||||||
|
|
||||||
|
[ToolshedCommand, AdminCommand(AdminFlags.Admin)]
|
||||||
|
public sealed class StationsCommand : ToolshedCommand
|
||||||
|
{
|
||||||
|
private StationSystem? _station;
|
||||||
|
|
||||||
|
[CommandImplementation("list")]
|
||||||
|
public IEnumerable<EntityUid> List()
|
||||||
|
{
|
||||||
|
_station ??= GetSys<StationSystem>();
|
||||||
|
|
||||||
|
return _station.GetStationsSet();
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandImplementation("get")]
|
||||||
|
public EntityUid Get([CommandInvocationContext] IInvocationContext ctx)
|
||||||
|
{
|
||||||
|
_station ??= GetSys<StationSystem>();
|
||||||
|
|
||||||
|
var set = _station.GetStationsSet();
|
||||||
|
if (set.Count > 1 || set.Count == 0)
|
||||||
|
ctx.ReportError(new OnlyOneStationsError());
|
||||||
|
|
||||||
|
return set.FirstOrDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandImplementation("getowningstation")]
|
||||||
|
public IEnumerable<EntityUid?> GetOwningStation([PipedArgument] IEnumerable<EntityUid> input)
|
||||||
|
=> input.Select(GetOwningStation);
|
||||||
|
|
||||||
|
[CommandImplementation("getowningstation")]
|
||||||
|
public EntityUid? GetOwningStation([PipedArgument] EntityUid input)
|
||||||
|
{
|
||||||
|
_station ??= GetSys<StationSystem>();
|
||||||
|
|
||||||
|
return _station.GetOwningStation(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandImplementation("largestgrid")]
|
||||||
|
public EntityUid? LargestGrid([PipedArgument] EntityUid input)
|
||||||
|
{
|
||||||
|
_station ??= GetSys<StationSystem>();
|
||||||
|
|
||||||
|
return _station.GetLargestGrid(Comp<StationDataComponent>(input));
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandImplementation("largestgrid")]
|
||||||
|
public IEnumerable<EntityUid?> LargestGrid([PipedArgument] IEnumerable<EntityUid> input)
|
||||||
|
=> input.Select(LargestGrid);
|
||||||
|
|
||||||
|
|
||||||
|
[CommandImplementation("grids")]
|
||||||
|
public IEnumerable<EntityUid> Grids([PipedArgument] EntityUid input)
|
||||||
|
=> Comp<StationDataComponent>(input).Grids;
|
||||||
|
|
||||||
|
[CommandImplementation("grids")]
|
||||||
|
public IEnumerable<EntityUid> Grids([PipedArgument] IEnumerable<EntityUid> input)
|
||||||
|
=> input.SelectMany(Grids);
|
||||||
|
|
||||||
|
[CommandImplementation("config")]
|
||||||
|
public StationConfig? Config([PipedArgument] EntityUid input)
|
||||||
|
=> Comp<StationDataComponent>(input).StationConfig;
|
||||||
|
|
||||||
|
[CommandImplementation("config")]
|
||||||
|
public IEnumerable<StationConfig?> Config([PipedArgument] IEnumerable<EntityUid> input)
|
||||||
|
=> input.Select(Config);
|
||||||
|
|
||||||
|
[CommandImplementation("addgrid")]
|
||||||
|
public void AddGrid(
|
||||||
|
[CommandInvocationContext] IInvocationContext ctx,
|
||||||
|
[PipedArgument] EntityUid input,
|
||||||
|
[CommandArgument] ValueRef<EntityUid> grid
|
||||||
|
)
|
||||||
|
{
|
||||||
|
_station ??= GetSys<StationSystem>();
|
||||||
|
|
||||||
|
_station.AddGridToStation(input, grid.Evaluate(ctx));
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandImplementation("rmgrid")]
|
||||||
|
public void RmGrid(
|
||||||
|
[CommandInvocationContext] IInvocationContext ctx,
|
||||||
|
[PipedArgument] EntityUid input,
|
||||||
|
[CommandArgument] ValueRef<EntityUid> grid
|
||||||
|
)
|
||||||
|
{
|
||||||
|
_station ??= GetSys<StationSystem>();
|
||||||
|
|
||||||
|
_station.RemoveGridFromStation(input, grid.Evaluate(ctx));
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandImplementation("rename")]
|
||||||
|
public void Rename([CommandInvocationContext] IInvocationContext ctx,
|
||||||
|
[PipedArgument] EntityUid input,
|
||||||
|
[CommandArgument] ValueRef<string> name
|
||||||
|
)
|
||||||
|
{
|
||||||
|
_station ??= GetSys<StationSystem>();
|
||||||
|
|
||||||
|
_station.RenameStation(input, name.Evaluate(ctx)!);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public record struct OnlyOneStationsError : IConError
|
||||||
|
{
|
||||||
|
public FormattedMessage DescribeInner()
|
||||||
|
{
|
||||||
|
return FormattedMessage.FromMarkup("This command doesn't function if there is more than one or no stations, explicitly specify a station with the ent command or similar.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public string? Expression { get; set; }
|
||||||
|
public Vector2i? IssueSpan { get; set; }
|
||||||
|
public StackTrace? Trace { get; set; }
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Shared.Console;
|
using Robust.Shared.Console;
|
||||||
|
using Robust.Shared.Toolshed;
|
||||||
|
|
||||||
namespace Content.Shared.Administration
|
namespace Content.Shared.Administration
|
||||||
{
|
{
|
||||||
@@ -7,7 +8,6 @@ namespace Content.Shared.Administration
|
|||||||
/// Specifies that a command can be executed by any player.
|
/// Specifies that a command can be executed by any player.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
|
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
|
||||||
[BaseTypeRequired(typeof(IConsoleCommand))]
|
|
||||||
[MeansImplicitUse]
|
[MeansImplicitUse]
|
||||||
public sealed class AnyCommandAttribute : Attribute
|
public sealed class AnyCommandAttribute : Attribute
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ using Robust.Shared.Serialization;
|
|||||||
namespace Content.Shared.Bql;
|
namespace Content.Shared.Bql;
|
||||||
|
|
||||||
[Serializable, NetSerializable]
|
[Serializable, NetSerializable]
|
||||||
public sealed class BqlResultsEuiState : EuiStateBase
|
public sealed class ToolshedVisualizeEuiState : EuiStateBase
|
||||||
{
|
{
|
||||||
public readonly (string name, EntityUid entity)[] Entities;
|
public readonly (string name, EntityUid entity)[] Entities;
|
||||||
|
|
||||||
public BqlResultsEuiState((string name, EntityUid entity)[] entities)
|
public ToolshedVisualizeEuiState((string name, EntityUid entity)[] entities)
|
||||||
{
|
{
|
||||||
Entities = entities;
|
Entities = entities;
|
||||||
}
|
}
|
||||||
@@ -7,3 +7,5 @@ admin-verbs-teleport-to = Teleport To
|
|||||||
admin-verbs-teleport-here = Teleport Here
|
admin-verbs-teleport-here = Teleport Here
|
||||||
admin-verbs-freeze = Freeze
|
admin-verbs-freeze = Freeze
|
||||||
admin-verbs-unfreeze = Unfreeze
|
admin-verbs-unfreeze = Unfreeze
|
||||||
|
toolshed-verb-mark = Mark
|
||||||
|
toolshed-verb-mark-description = Places this entity into the $marked variable, a list of entities, replacing it's prior value.
|
||||||
|
|||||||
56
Resources/Locale/en-US/commands/toolshed-commands.ftl
Normal file
56
Resources/Locale/en-US/commands/toolshed-commands.ftl
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
command-description-visualize =
|
||||||
|
Takes the input list of entities and puts them into a UI window for easy browsing.
|
||||||
|
command-description-runverbas =
|
||||||
|
Runs a verb over the input entities with the given user.
|
||||||
|
command-description-acmd-perms =
|
||||||
|
Returns the admin permissions of the given command, if any.
|
||||||
|
command-description-acmd-caninvoke =
|
||||||
|
Check if the given player can invoke the given command.
|
||||||
|
command-description-jobs-jobs =
|
||||||
|
Returns all jobs on a station.
|
||||||
|
command-description-jobs-job =
|
||||||
|
Returns a given job on a station.
|
||||||
|
command-description-jobs-isinfinite =
|
||||||
|
Returns true if the input job is infinite, otherwise false.
|
||||||
|
command-description-jobs-adjust =
|
||||||
|
Adjusts the number of slots for the given job.
|
||||||
|
command-description-jobs-set =
|
||||||
|
Sets the number of slots for the given job.
|
||||||
|
command-description-jobs-amount =
|
||||||
|
Returns the number of slots for the given job.
|
||||||
|
command-description-stations-list =
|
||||||
|
Returns a list of all stations.
|
||||||
|
command-description-stations-get =
|
||||||
|
Gets the active station, if and only if there is only one.
|
||||||
|
command-description-stations-getowningstation =
|
||||||
|
Gets the station that a given entity is "owned by" (within)
|
||||||
|
command-description-stations-grids =
|
||||||
|
Returns all grids associated with the input station.
|
||||||
|
command-description-stations-config =
|
||||||
|
Returns the config associated with the input station, if any.
|
||||||
|
command-description-stations-addgrid =
|
||||||
|
Adds a grid to the given station.
|
||||||
|
command-description-stations-rmgrid =
|
||||||
|
Removes a grid from the given station.
|
||||||
|
command-description-stations-rename =
|
||||||
|
Renames the given station.
|
||||||
|
command-description-stations-largestgrid =
|
||||||
|
Returns the largest grid the given station has, if any.
|
||||||
|
command-description-admins-active =
|
||||||
|
Returns a list of active admins.
|
||||||
|
command-description-admins-all =
|
||||||
|
Returns a list of ALL admins, including deadmined ones.
|
||||||
|
command-description-marked =
|
||||||
|
Returns the value of $marked as a List<EntityUid>.
|
||||||
|
command-description-rejuvenate =
|
||||||
|
Rejuvenates the given entities, restoring them to full health, clearing status effects, etc.
|
||||||
|
command-description-tag-list =
|
||||||
|
Lists tags on the given entities.
|
||||||
|
command-description-tag-add =
|
||||||
|
Adds a tag to the given entities.
|
||||||
|
command-description-tag-rm =
|
||||||
|
Removes a tag from the given entities.
|
||||||
|
command-description-tag-addmany =
|
||||||
|
Adds a list of tags to the given entities.
|
||||||
|
command-description-tag-rmmany =
|
||||||
|
Removes a list of tags from the given entities.
|
||||||
@@ -126,7 +126,9 @@
|
|||||||
|
|
||||||
- Flags: QUERY
|
- Flags: QUERY
|
||||||
Commands:
|
Commands:
|
||||||
- forall
|
|
||||||
- uploadfile
|
- uploadfile
|
||||||
- loadprototype
|
- loadprototype
|
||||||
- uploadfolder
|
- uploadfolder
|
||||||
|
|
||||||
|
- Commands:
|
||||||
|
- "|"
|
||||||
|
|||||||
70
Resources/toolshedEngineCommandPerms.yml
Normal file
70
Resources/toolshedEngineCommandPerms.yml
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
- Flags: QUERY
|
||||||
|
Commands:
|
||||||
|
- entities
|
||||||
|
- nearby
|
||||||
|
- map
|
||||||
|
- physics
|
||||||
|
- player
|
||||||
|
- splat
|
||||||
|
- emplace
|
||||||
|
|
||||||
|
- Flags: DEBUG
|
||||||
|
Commands:
|
||||||
|
- comp
|
||||||
|
- delete
|
||||||
|
- do
|
||||||
|
- named
|
||||||
|
- paused
|
||||||
|
- with
|
||||||
|
- count
|
||||||
|
- select
|
||||||
|
- where
|
||||||
|
- prototyped
|
||||||
|
- types
|
||||||
|
- ecscomp
|
||||||
|
- actor
|
||||||
|
|
||||||
|
- Flags: HOST
|
||||||
|
Commands:
|
||||||
|
- methods
|
||||||
|
- ioc
|
||||||
|
|
||||||
|
- Commands:
|
||||||
|
- fuck
|
||||||
|
- ent
|
||||||
|
- as
|
||||||
|
- buildinfo
|
||||||
|
- help
|
||||||
|
- explain
|
||||||
|
- cmd
|
||||||
|
- stopwatch
|
||||||
|
- self
|
||||||
|
- search
|
||||||
|
- isnull
|
||||||
|
- help
|
||||||
|
- isempty
|
||||||
|
- any
|
||||||
|
- unique
|
||||||
|
- cd
|
||||||
|
- ls
|
||||||
|
- loc
|
||||||
|
- vars
|
||||||
|
- '=>'
|
||||||
|
- first
|
||||||
|
- val
|
||||||
|
- '+'
|
||||||
|
- '-'
|
||||||
|
- '*'
|
||||||
|
- '/'
|
||||||
|
- 'min'
|
||||||
|
- 'max'
|
||||||
|
- '&'
|
||||||
|
- '|'
|
||||||
|
- '^'
|
||||||
|
- 'neg'
|
||||||
|
- '<'
|
||||||
|
- '>'
|
||||||
|
- '<='
|
||||||
|
- '>='
|
||||||
|
- '=='
|
||||||
|
- '!='
|
||||||
Submodule RobustToolbox updated: a7315b1c95...cf91369d27
@@ -604,6 +604,8 @@ public sealed class $CLASS$ : Shared$CLASS$ {
|
|||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Thonk/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Thonk/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=threadsafe/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=threadsafe/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=tickrate/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=tickrate/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Toolshed/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Toolshed_0027s/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Trasen/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Trasen/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=unanchor/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=unanchor/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Unanchored/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Unanchored/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
|||||||
Reference in New Issue
Block a user