Files
RobustToolbox/Robust.Shared/Toolshed/Commands/Generic/EmplaceCommand.cs
Moony 0e1328675c Toolshed (#4197)
* Saving work

* Move shit to engine

* lord

* merg

* awa

* bql is kill

* forgot the fucking bike rack

* bql is kill for real

* pjb will kill me

* aughfhbdj

* yo ho here we go on my way to the MINES

* a

* adgddf

* gdsgvfvxshngfgh

* b

* hfsjhghj

* hbfdjjh

* 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.

* Fix valueref up a bit, improve autocomplete for it.

* e

* Toolshed type system adventure.

* a log

* a

* a e i o u

* awa

* fix tests

* Arithmetic commands.

* a

* parse improvements

---------

Co-authored-by: moonheart08 <moonheart08@users.noreply.github.com>
2023-08-02 16:06:16 -05:00

158 lines
4.2 KiB
C#

using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using Robust.Shared.GameObjects;
using Robust.Shared.Players;
using Robust.Shared.Toolshed.Errors;
using Robust.Shared.Toolshed.Syntax;
namespace Robust.Shared.Toolshed.Commands.Generic;
[ToolshedCommand, MapLikeCommand(false)]
internal sealed class EmplaceCommand : ToolshedCommand
{
[CommandImplementation]
IEnumerable<TOut> Emplace<TIn, TOut>(
[CommandInvocationContext] IInvocationContext ctx,
[PipedArgument] IEnumerable<TIn> value,
[CommandArgument] Block<TOut> block
)
{
foreach (var v in value)
{
var emplaceCtx = new EmplaceContext<TIn>(ctx, v, EntityManager);
yield return block.Invoke(null, emplaceCtx)!;
}
}
}
internal record struct EmplaceContext<T>(IInvocationContext Inner, T Value, IEntityManager EntityManager) : IInvocationContext
{
public bool CheckInvokable(CommandSpec command, out IConError? error)
{
return Inner.CheckInvokable(command, out error);
}
public ICommonSession? Session => Inner.Session;
public void WriteLine(string line)
{
Inner.WriteLine(line);
}
public void ReportError(IConError err)
{
Inner.ReportError(err);
}
public IEnumerable<IConError> GetErrors()
{
return Inner.GetErrors();
}
public void ClearErrors()
{
Inner.ClearErrors();
}
public Dictionary<string, object?> Variables => default!; // we never use this.
public IEnumerable<string> GetVars()
{
// note: this lies.
return Inner.GetVars();
}
public object? ReadVar(string name)
{
if (name == "value")
return Value;
if (Value is IEmplaceBreakout breakout)
{
if (breakout.TryReadVar(name, out var value))
return value;
}
// TODO: Emplace behavior should be generalized and not hardcoded.
if (Value is EntityUid id)
{
switch (name)
{
case "wy":
case "wx":
{
var xform = EntityManager.GetComponent<TransformComponent>(id);
var sys = EntityManager.System<SharedTransformSystem>();
var coords = sys.GetWorldPosition(xform);
if (name == "wx")
return coords.X;
else
return coords.Y;
}
case "proto":
case "desc":
case "name":
case "paused":
{
var meta = EntityManager.GetComponent<MetaDataComponent>(id);
switch (name)
{
case "proto":
return meta.EntityPrototype?.ID ?? "";
case "desc":
return meta.EntityDescription;
case "name":
return meta.EntityName;
case "paused":
return meta.EntityPaused;
}
throw new UnreachableException();
}
}
}
else if (Value is ICommonSession session)
{
switch (name)
{
case "ent":
{
return session.AttachedEntity!;
}
case "name":
{
return session.Name;
}
case "userid":
{
return session.UserId;
}
}
}
return Inner.ReadVar(name);
}
public void WriteVar(string name, object? value)
{
if (name == "value")
return;
if (Value is IEmplaceBreakout v)
{
if (v.VarsOverriden.Contains(name))
return;
}
Inner.WriteVar(name, value);
}
}
public interface IEmplaceBreakout
{
public ImmutableHashSet<string> VarsOverriden { get; }
public bool TryReadVar(string name, out object? value);
}