mirror of
https://github.com/space-syndicate/space-station-14.git
synced 2026-10-09 10:21:18 +03:00
Additional console commands for debugging Xeno Artifact (#41455)
* feat: xeno artifact debug commands * refactor: minor renaming + whitespaces * refactor: do not allocate unless needed * refactor: rename common xeno-artifact commands localization string * refactor: extract reusable parts of code, change command to work with EntityUid and not with NetEntity * refactor: renaming * refactor: make all commands toolshed * refactor: localization fix, command naming reverted to camelCase, xml-doc for new commands * refactor: make toolshed tuple actually work * refactor: remove unused code * refactor: cache for EffectPrototypes * refactor: fix unlcokNode command, remove engine copy-paste for TryParseEntity * refactor: fix localization for toolshed * refactor: remove unused dependency * refactor: caching systems for XenoArtifactCommand where possible, comments clarification, whitespacing * refactor: added readonly to SharedXenoArtifactSystem.EffectPrototypeIds * refactor: use component to detect which proto is xenoarch effect * refactor: fix missing partial for XenoArtifactCommand * refactor: fix readonly on dependencies for XenoArtifactCommand * refactor: fix missing partial for nested XenoArtifact related parsers * refactor: cleanup after merge * refactor: remove obsolete IPrototype.HasComponent call and unused using * refactor: change xenoarch commands to lowercase (as convention dictates) * refactor: XenoArtifactNodeParser and XenoArtifactTypeParser are now CustomCompletionParser (removed duplicate code) * refactor: XenoArtifactNodeParser is now CustomCompletionParser, moved custom parsers to shared/toolshed/parsers * refactor: todo for ent proto caching, moved XenoArtifactCommand to toolshed namespace * refactor: fix xenoartifact:totalresearch command * refactor: remove system caching, clean whitespaces * fix: fix localization for xenoarch commands * refactor: moved StatusEffectCompletionParser to shared, added same todo remark for cache of status effect entity prototypes. * refactor: use proxy methods in command and _entityManager.System in all parsers * refactor: mved commands and parsers into respective folders * refactor: access restriction for cached EntityPrototypeIds * refactor: todo link to issue, fixed DI in StatusEffectCompletionParser --------- Co-authored-by: pa.pecherskij <pa.pecherskij@interfax.ru>
This commit is contained in:
parent
d2472f82ed
commit
bb5f8d696a
17 changed files with 469 additions and 222 deletions
|
|
@ -1,4 +1,4 @@
|
|||
using Content.Shared.Station.Components;
|
||||
using Content.Shared.Station.Components;
|
||||
using Robust.Shared.Console;
|
||||
|
||||
namespace Content.Server.Commands;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
using Content.Server.Administration;
|
||||
using Content.Server.Toolshed.TypeParsers.StatusEffects;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.StatusEffectNew;
|
||||
using Content.Shared.Toolshed.TypeParsers;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Toolshed;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,242 @@
|
|||
using System.Text;
|
||||
using Content.Server.Administration;
|
||||
using Content.Server.Xenoarchaeology.Artifact;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Toolshed.TypeParsers.XenoArtifact;
|
||||
using Content.Shared.Xenoarchaeology.Artifact.Components;
|
||||
using Content.Shared.Xenoarchaeology.Artifact.Prototypes;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Toolshed;
|
||||
|
||||
namespace Content.Server.Toolshed.Commands.XenoArtifacts;
|
||||
|
||||
/// <summary>
|
||||
/// Toolshed commands for manipulating xeno artifact.
|
||||
/// </summary>
|
||||
[ToolshedCommand, AdminCommand(AdminFlags.Debug)]
|
||||
public sealed partial class XenoArtifactCommand : ToolshedCommand
|
||||
{
|
||||
[Dependency] private IPrototypeManager _prototypeManager = default!;
|
||||
|
||||
private XenoArtifactSystem? _artifact;
|
||||
|
||||
public static readonly EntProtoId ArtifactPrototype = "ComplexXenoArtifactItem";
|
||||
|
||||
/// <summary> List existing artifacts. </summary>
|
||||
[CommandImplementation("list")]
|
||||
public IEnumerable<EntityUid> List()
|
||||
{
|
||||
var query = EntityManager.EntityQueryEnumerator<XenoArtifactComponent>();
|
||||
while (query.MoveNext(out var uid, out _))
|
||||
{
|
||||
yield return uid;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Output matrix of artifact nodes and how they are connected.
|
||||
/// </summary>
|
||||
[CommandImplementation("printmatrix")]
|
||||
public string PrintMatrix([CommandArgument] Entity<XenoArtifactComponent> artifactEnt)
|
||||
{
|
||||
var nodeCount = artifactEnt.Comp.NodeVertices.Length;
|
||||
|
||||
var sb = new StringBuilder("\n |");
|
||||
for (var i = 0; i < nodeCount; i++)
|
||||
{
|
||||
sb.Append($" {i:D2}|");
|
||||
}
|
||||
|
||||
AddHorizontalFiller(sb);
|
||||
|
||||
for (var i = 0; i < nodeCount; i++)
|
||||
{
|
||||
sb.Append($"\n{i:D2}|");
|
||||
for (var j = 0; j < nodeCount; j++)
|
||||
{
|
||||
var value = artifactEnt.Comp.NodeAdjacencyMatrix[i][j]
|
||||
? "X"
|
||||
: " ";
|
||||
sb.Append($" {value} |");
|
||||
}
|
||||
AddHorizontalFiller(sb);
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
|
||||
void AddHorizontalFiller(StringBuilder builder)
|
||||
{
|
||||
builder.AppendLine();
|
||||
builder.Append("--+");
|
||||
for (var i = 0; i < nodeCount; i++)
|
||||
{
|
||||
builder.Append("---+");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Output total research points artifact contains. </summary>
|
||||
[CommandImplementation("totalresearch")]
|
||||
public int TotalResearch([PipedArgument] EntityUid artifactEntityUid)
|
||||
{
|
||||
_artifact ??= Sys<XenoArtifactSystem>();
|
||||
var comp = Comp<XenoArtifactComponent>(artifactEntityUid);
|
||||
|
||||
var sum = 0;
|
||||
|
||||
var nodes = _artifact.GetAllNodes((artifactEntityUid, comp));
|
||||
foreach (var node in nodes)
|
||||
{
|
||||
sum += node.Comp.ResearchValue;
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Spawns a bunch of artifacts and gets average total research points they can yield.
|
||||
/// </summary>
|
||||
[CommandImplementation("averageresearch")]
|
||||
public float AverageResearch()
|
||||
{
|
||||
const int n = 100;
|
||||
var sum = 0;
|
||||
|
||||
for (var i = 0; i < n; i++)
|
||||
{
|
||||
var ent = Spawn(ArtifactPrototype, MapCoordinates.Nullspace);
|
||||
sum += TotalResearch(ent);
|
||||
Del(ent);
|
||||
}
|
||||
|
||||
return (float)sum / n;
|
||||
}
|
||||
|
||||
/// <summary> Unlocks all nodes of artifact. </summary>
|
||||
[CommandImplementation("unlockallnodes")]
|
||||
public void UnlockAllNodes([PipedArgument] EntityUid artifactEntityUid)
|
||||
{
|
||||
_artifact ??= Sys<XenoArtifactSystem>();
|
||||
var comp = Comp<XenoArtifactComponent>(artifactEntityUid);
|
||||
|
||||
var nodes = _artifact.GetAllNodes((artifactEntityUid, comp));
|
||||
foreach (var node in nodes)
|
||||
{
|
||||
_artifact.SetNodeUnlocked((node, node.Comp));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create node in artifact (new on depth 0 or attach next to existing one).
|
||||
/// </summary>
|
||||
[CommandImplementation("createnode")]
|
||||
public void CreateNodeNew(
|
||||
[CommandArgument] Entity<XenoArtifactComponent> artifact,
|
||||
[CommandArgument(typeof(XenoEffectParser))] ProtoId<EntityPrototype> effect,
|
||||
[CommandArgument] ProtoId<XenoArchTriggerPrototype> trigger
|
||||
)
|
||||
{
|
||||
CreateNode(artifact, effect, trigger);
|
||||
}
|
||||
|
||||
/// <summary> Add a new node to the given artifact. </summary>
|
||||
[CommandImplementation("createnodeatdepth")]
|
||||
public void CreateNodeAtDepth(
|
||||
[CommandArgument(typeof(XenoArtifactNodeParser))] (Entity<XenoArtifactComponent> Artifact, Entity<XenoArtifactNodeComponent> Node) tuple,
|
||||
[CommandArgument(typeof(XenoEffectParser))] ProtoId<EntityPrototype> effect,
|
||||
[CommandArgument] ProtoId<XenoArchTriggerPrototype> trigger
|
||||
)
|
||||
{
|
||||
CreateNode(tuple.Artifact, effect, trigger, tuple.Node);
|
||||
}
|
||||
|
||||
/// <summary> Spawns a new xeno artifact with single node with the given trigger and effect. </summary>
|
||||
[CommandImplementation("spawnartwithnode")]
|
||||
public void SpawnArtifactWithNode(
|
||||
[CommandArgument] ICommonSession target,
|
||||
[CommandArgument(typeof(XenoArtifactTypeParser))] ProtoId<EntityPrototype> artifactType,
|
||||
[CommandArgument(typeof(XenoEffectParser))] ProtoId<EntityPrototype> effect,
|
||||
[CommandArgument] ProtoId<XenoArchTriggerPrototype> trigger
|
||||
)
|
||||
{
|
||||
if (target.AttachedEntity == null)
|
||||
return;
|
||||
|
||||
var entity = EntityManager.SpawnNextToOrDrop(artifactType, target.AttachedEntity.Value);
|
||||
if (!TryComp(entity, out XenoArtifactComponent? artifactComp))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CreateNode((entity, artifactComp), effect, trigger);
|
||||
}
|
||||
|
||||
/// <summary> Marks a node as unlocked. </summary>
|
||||
[CommandImplementation("unlocknode")]
|
||||
public void UnlockNode(
|
||||
[CommandArgument(typeof(XenoArtifactNodeParser))]
|
||||
(Entity<XenoArtifactComponent> Artifact, Entity<XenoArtifactNodeComponent> Node) tuple
|
||||
)
|
||||
{
|
||||
_artifact ??= Sys<XenoArtifactSystem>();
|
||||
_artifact.SetNodeUnlocked(tuple.Node.AsNullable());
|
||||
}
|
||||
|
||||
/// <summary> Removes a node from a xeno artifact. </summary>
|
||||
[CommandImplementation("removenode")]
|
||||
public void RemoveNode(
|
||||
[CommandArgument(typeof(XenoArtifactNodeParser))]
|
||||
(Entity<XenoArtifactComponent> Artifact, Entity<XenoArtifactNodeComponent> Node) tuple
|
||||
)
|
||||
{
|
||||
_artifact ??= Sys<XenoArtifactSystem>();
|
||||
_artifact.RemoveNode(tuple.Artifact.AsNullable(), tuple.Node.AsNullable());
|
||||
}
|
||||
|
||||
/// <summary> Adds an edge between two nodes of a xeno artifact. </summary>
|
||||
[CommandImplementation("addedge")]
|
||||
public void AddEdge(
|
||||
[CommandArgument(typeof(XenoArtifactNodeParser))]
|
||||
(Entity<XenoArtifactComponent> Artifact, Entity<XenoArtifactNodeComponent> Node) from,
|
||||
[CommandArgument(typeof(XenoArtifactNodeParser))]
|
||||
(Entity<XenoArtifactComponent> Artifact, Entity<XenoArtifactNodeComponent> Node) to
|
||||
)
|
||||
{
|
||||
// no inter-artifact edges or self-connects allowed
|
||||
if (from.Artifact.Owner != to.Artifact.Owner || from.Node.Owner == to.Node.Owner)
|
||||
return;
|
||||
|
||||
_artifact = Sys<XenoArtifactSystem>();
|
||||
_artifact.AddEdge(from.Artifact.AsNullable(), from.Node, to.Node);
|
||||
}
|
||||
|
||||
private void CreateNode(
|
||||
Entity<XenoArtifactComponent> artifact,
|
||||
ProtoId<EntityPrototype> effect,
|
||||
ProtoId<XenoArchTriggerPrototype> trigger,
|
||||
Entity<XenoArtifactNodeComponent>? node = null
|
||||
)
|
||||
{
|
||||
var depth = 0;
|
||||
if (node.HasValue)
|
||||
{
|
||||
depth = node.Value.Comp.Depth + 1;
|
||||
}
|
||||
|
||||
_artifact ??= Sys<XenoArtifactSystem>();
|
||||
if (!_prototypeManager.Resolve(trigger, out var triggerPrototype))
|
||||
return;
|
||||
|
||||
var createdNode = _artifact.CreateNode(artifact, effect.Id, triggerPrototype, depth);
|
||||
if (node.HasValue)
|
||||
{
|
||||
_artifact.AddEdge(artifact.AsNullable(), node.Value, createdNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
_artifact.RebuildXenoArtifactMetaData(artifact.AsNullable());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
using Content.Shared.StatusEffectNew;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Toolshed;
|
||||
using Robust.Shared.Toolshed.Syntax;
|
||||
using Robust.Shared.Toolshed.TypeParsers;
|
||||
|
||||
namespace Content.Server.Toolshed.TypeParsers.StatusEffects;
|
||||
|
||||
public sealed class StatusEffectCompletionParser : CustomCompletionParser<EntProtoId>
|
||||
{
|
||||
public override CompletionResult? TryAutocomplete(ParserContext ctx, CommandArgument? arg)
|
||||
{
|
||||
return CompletionResult.FromHintOptions(IoCManager.Resolve<IEntityManager>().System<StatusEffectsSystem>().StatusEffectPrototypes, GetArgHint(arg));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
using Content.Server.Administration;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Xenoarchaeology.Artifact.Components;
|
||||
using Robust.Shared.Console;
|
||||
|
||||
namespace Content.Server.Xenoarchaeology.Artifact;
|
||||
|
||||
/// <summary> Command for unlocking a specific node of a xeno artifact. </summary>
|
||||
[AdminCommand(AdminFlags.Debug)]
|
||||
public sealed partial class UnlockNodeCommand : LocalizedEntityCommands
|
||||
{
|
||||
[Dependency] private XenoArtifactSystem _artiSystem = default!;
|
||||
|
||||
public override string Command => "unlocknode";
|
||||
|
||||
public override void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (args.Length != 2)
|
||||
{
|
||||
shell.WriteError(Loc.GetString("shell-wrong-arguments-number"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!NetEntity.TryParse(args[1], out var netNode) || !EntityManager.TryGetEntity(netNode, out var entityUid))
|
||||
{
|
||||
shell.WriteError(Loc.GetString("shell-could-not-find-entity-with-uid", ("uid", args[1])));
|
||||
return;
|
||||
}
|
||||
|
||||
_artiSystem.SetNodeUnlocked(entityUid.Value);
|
||||
}
|
||||
|
||||
public override CompletionResult GetCompletion(IConsoleShell shell, string[] args)
|
||||
{
|
||||
switch (args.Length)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
var query = EntityManager.EntityQueryEnumerator<XenoArtifactComponent>();
|
||||
var completionOptions = new List<CompletionOption>();
|
||||
while (query.MoveNext(out var uid, out _))
|
||||
{
|
||||
completionOptions.Add(new CompletionOption(uid.ToString()));
|
||||
}
|
||||
|
||||
return CompletionResult.FromHintOptions(completionOptions, Loc.GetString("cmd-unlocknode-artifact-hint"));
|
||||
}
|
||||
case 2 when
|
||||
NetEntity.TryParse(args[0], out var netEnt) &&
|
||||
EntityManager.TryGetEntity(netEnt, out var artifactUid) &&
|
||||
EntityManager.TryGetComponent<XenoArtifactComponent>(artifactUid, out var comp):
|
||||
{
|
||||
var result = new List<CompletionOption>();
|
||||
foreach (var node in _artiSystem.GetAllNodes((artifactUid.Value, comp)))
|
||||
{
|
||||
var metaData = EntityManager.MetaQuery.Comp(artifactUid.Value);
|
||||
var entityUidStr = EntityManager.GetNetEntity(node).ToString();
|
||||
var completionOption = new CompletionOption(entityUidStr, metaData.EntityName);
|
||||
result.Add(completionOption);
|
||||
}
|
||||
|
||||
return CompletionResult.FromHintOptions(result, Loc.GetString("cmd-unlocknode-node-hint"));
|
||||
}
|
||||
default:
|
||||
return CompletionResult.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,124 +0,0 @@
|
|||
using System.Text;
|
||||
using Content.Server.Administration;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Xenoarchaeology.Artifact.Components;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Toolshed;
|
||||
|
||||
namespace Content.Server.Xenoarchaeology.Artifact;
|
||||
|
||||
/// <summary>
|
||||
/// Toolshed commands for manipulating xeno artifact.
|
||||
/// </summary>
|
||||
[ToolshedCommand, AdminCommand(AdminFlags.Debug)]
|
||||
public sealed class XenoArtifactCommand : ToolshedCommand
|
||||
{
|
||||
public static readonly EntProtoId ArtifactPrototype = "BaseXenoArtifact";
|
||||
|
||||
/// <summary> List existing artifacts. </summary>
|
||||
[CommandImplementation("list")]
|
||||
public IEnumerable<EntityUid> List()
|
||||
{
|
||||
var query = EntityManager.EntityQueryEnumerator<XenoArtifactComponent>();
|
||||
while (query.MoveNext(out var uid, out _))
|
||||
{
|
||||
yield return uid;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Output matrix of artifact nodes and how they are connected.
|
||||
/// </summary>
|
||||
[CommandImplementation("printMatrix")]
|
||||
public string PrintMatrix([PipedArgument] EntityUid artifactEntitUid)
|
||||
{
|
||||
var comp = EntityManager.GetComponent<XenoArtifactComponent>(artifactEntitUid);
|
||||
|
||||
var nodeCount = comp.NodeVertices.Length;
|
||||
|
||||
var sb = new StringBuilder("\n |");
|
||||
for (var i = 0; i < nodeCount; i++)
|
||||
{
|
||||
sb.Append($" {i:D2}|");
|
||||
}
|
||||
|
||||
AddHorizontalFiller(sb);
|
||||
|
||||
for (var i = 0; i < nodeCount; i++)
|
||||
{
|
||||
sb.Append($"\n{i:D2}|");
|
||||
for (var j = 0; j < nodeCount; j++)
|
||||
{
|
||||
var value = comp.NodeAdjacencyMatrix[i][j]
|
||||
? "X"
|
||||
: " ";
|
||||
sb.Append($" {value} |");
|
||||
}
|
||||
AddHorizontalFiller(sb);
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
|
||||
void AddHorizontalFiller(StringBuilder builder)
|
||||
{
|
||||
builder.AppendLine();
|
||||
builder.Append("--+");
|
||||
for (var i = 0; i < nodeCount; i++)
|
||||
{
|
||||
builder.Append($"---+");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Output total research points artifact contains. </summary>
|
||||
[CommandImplementation("totalResearch")]
|
||||
public int TotalResearch([PipedArgument] EntityUid artifactEntityUid)
|
||||
{
|
||||
var artiSys = EntityManager.System<XenoArtifactSystem>();
|
||||
var comp = EntityManager.GetComponent<XenoArtifactComponent>(artifactEntityUid);
|
||||
|
||||
var sum = 0;
|
||||
|
||||
var nodes = artiSys.GetAllNodes((artifactEntityUid, comp));
|
||||
foreach (var node in nodes)
|
||||
{
|
||||
sum += node.Comp.ResearchValue;
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Spawns a bunch of artifacts and gets average total research points they can yield.
|
||||
/// </summary>
|
||||
[CommandImplementation("averageResearch")]
|
||||
public float AverageResearch()
|
||||
{
|
||||
const int n = 100;
|
||||
var sum = 0;
|
||||
|
||||
for (var i = 0; i < n; i++)
|
||||
{
|
||||
var ent = Spawn(ArtifactPrototype, MapCoordinates.Nullspace);
|
||||
sum += TotalResearch(ent);
|
||||
Del(ent);
|
||||
}
|
||||
|
||||
return (float) sum / n;
|
||||
}
|
||||
|
||||
/// <summary> Unlocks all nodes of artifact. </summary>
|
||||
[CommandImplementation("unlockAllNodes")]
|
||||
public void UnlockAllNodes([PipedArgument] EntityUid artifactEntityUid)
|
||||
{
|
||||
var artiSys = EntityManager.System<XenoArtifactSystem>();
|
||||
var comp = EntityManager.GetComponent<XenoArtifactComponent>(artifactEntityUid);
|
||||
|
||||
var nodes = artiSys.GetAllNodes((artifactEntityUid, comp));
|
||||
foreach (var node in nodes)
|
||||
{
|
||||
artiSys.SetNodeUnlocked((node, node.Comp));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +1,11 @@
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using Content.Shared.Rejuvenate;
|
||||
using Content.Shared.StatusEffectNew.Components;
|
||||
using Content.Shared.Toolshed.TypeParsers;
|
||||
using Content.Shared.Whitelist;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Timing;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Content.Shared.StatusEffectNew;
|
||||
|
||||
|
|
@ -21,6 +22,8 @@ public sealed partial class StatusEffectsSystem : EntitySystem
|
|||
[Dependency] private EntityQuery<StatusEffectContainerComponent> _containerQuery = default!;
|
||||
[Dependency] private EntityQuery<StatusEffectComponent> _effectQuery = default!;
|
||||
|
||||
// TODO: https://github.com/space-wizards/space-station-14/issues/45060
|
||||
[Access(typeof(StatusEffectCompletionParser), Other = AccessPermissions.None)]
|
||||
public readonly HashSet<string> StatusEffectPrototypes = [];
|
||||
|
||||
public override void Initialize()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
using Content.Shared.StatusEffectNew;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Toolshed;
|
||||
using Robust.Shared.Toolshed.Syntax;
|
||||
using Robust.Shared.Toolshed.TypeParsers;
|
||||
|
||||
namespace Content.Shared.Toolshed.TypeParsers;
|
||||
|
||||
public sealed partial class StatusEffectCompletionParser : CustomCompletionParser<EntProtoId>
|
||||
{
|
||||
[Dependency] private IEntityManager _entityManager = default!;
|
||||
|
||||
public override CompletionResult? TryAutocomplete(ParserContext ctx, CommandArgument? arg)
|
||||
{
|
||||
var statusEffects = _entityManager.System<StatusEffectsSystem>();
|
||||
return CompletionResult.FromHintOptions(statusEffects.StatusEffectPrototypes, GetArgHint(arg));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
using System.Linq;
|
||||
using Content.Shared.Xenoarchaeology.Artifact;
|
||||
using Content.Shared.Xenoarchaeology.Artifact.Components;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.Toolshed;
|
||||
using Robust.Shared.Toolshed.Syntax;
|
||||
using Robust.Shared.Toolshed.TypeParsers;
|
||||
|
||||
namespace Content.Shared.Toolshed.TypeParsers.XenoArtifact;
|
||||
|
||||
/// <summary>
|
||||
/// Argument parser for toolshed commands, which should autocomplete artifact nodes that exists on artifact.
|
||||
/// </summary>
|
||||
public sealed partial class XenoArtifactNodeParser : CustomCompletionParser<(Entity<XenoArtifactComponent>, Entity<XenoArtifactNodeComponent>)>
|
||||
{
|
||||
[Dependency] private IEntityManager _entityManager = default!;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override CompletionResult? TryAutocomplete(ParserContext ctx, CommandArgument? arg)
|
||||
{
|
||||
if (!Toolshed.TryParse<Entity<XenoArtifactComponent>>(ctx, out var artifactEnt))
|
||||
{
|
||||
return GetHintedEntities<XenoArtifactComponent>(arg);
|
||||
}
|
||||
|
||||
var hint = ToolshedCommand.GetArgHint(arg, typeof(Entity<XenoArtifactNodeComponent>));
|
||||
|
||||
var artifact = _entityManager.System<SharedXenoArtifactSystem>();
|
||||
var list = artifact.GetAllNodes(artifactEnt)
|
||||
.Select(
|
||||
node =>
|
||||
{
|
||||
var metadata = _entityManager.GetComponent<MetaDataComponent>(node);
|
||||
var entDescription = Loc.GetString(metadata.EntityDescription);
|
||||
return new CompletionOption(
|
||||
node.Owner.ToString(),
|
||||
Loc.GetString(
|
||||
"command-xenoartifact-common-node-hint",
|
||||
("depth", node.Comp.Depth),
|
||||
("nodeId", artifact.GetNodeId(node.Owner)),
|
||||
("nodeDetail", entDescription)
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
return CompletionResult.FromHintOptions(list, hint);
|
||||
}
|
||||
|
||||
private CompletionResult? GetHintedEntities<T>(CommandArgument? arg) where T : IComponent
|
||||
{
|
||||
var hint = ToolshedCommand.GetArgHint(arg, typeof(NetEntity));
|
||||
|
||||
// Avoid dumping too many entities
|
||||
if (_entityManager.Count<T>() > 128)
|
||||
return CompletionResult.FromHint(hint);
|
||||
|
||||
var query = _entityManager.AllEntityQueryEnumerator<T, MetaDataComponent>();
|
||||
var list = new List<CompletionOption>();
|
||||
while (query.MoveNext(out _, out var metadata))
|
||||
{
|
||||
list.Add(new CompletionOption(metadata.NetEntity.ToString(), metadata.EntityName));
|
||||
}
|
||||
|
||||
return CompletionResult.FromHintOptions(list, hint);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
using Robust.Shared.Console;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Toolshed;
|
||||
using Robust.Shared.Toolshed.Syntax;
|
||||
using Robust.Shared.Toolshed.TypeParsers;
|
||||
|
||||
namespace Content.Shared.Toolshed.TypeParsers.XenoArtifact;
|
||||
|
||||
/// <summary>
|
||||
/// Custom type parser for toolshed commands that will enable choosing between hand-held and
|
||||
/// stationary artifact types.
|
||||
/// </summary>
|
||||
public sealed partial class XenoArtifactTypeParser : CustomCompletionParser<ProtoId<EntityPrototype>>
|
||||
{
|
||||
private static readonly EntProtoId ArtifactDummyItem = "DummyArtifactItem";
|
||||
private static readonly EntProtoId ArtifactDummyStructure = "DummyArtifactStructure";
|
||||
|
||||
public override CompletionResult TryAutocomplete(ParserContext ctx, CommandArgument? arg)
|
||||
{
|
||||
return CompletionResult.FromHintOptions(
|
||||
[
|
||||
new CompletionOption(ArtifactDummyItem, Loc.GetString("command-spawnartifactwithnode-spawn-artifact-item-hint")),
|
||||
new CompletionOption(ArtifactDummyStructure, Loc.GetString("command-spawnartifactwithnode-spawn-artifact-structure-hint")),
|
||||
],
|
||||
Loc.GetString("command-spawnartifactwithnode-spawn-artifact-type-hint")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
using Content.Shared.Xenoarchaeology.Artifact;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Toolshed;
|
||||
using Robust.Shared.Toolshed.Syntax;
|
||||
using Robust.Shared.Toolshed.TypeParsers;
|
||||
|
||||
namespace Content.Shared.Toolshed.TypeParsers.XenoArtifact;
|
||||
|
||||
/// <summary>
|
||||
/// Custom type parser for toolshed commands
|
||||
/// that lets choose entity prototype of XenoArtifact effect.
|
||||
/// </summary>
|
||||
public sealed partial class XenoEffectParser : CustomCompletionParser<ProtoId<EntityPrototype>>
|
||||
{
|
||||
[Dependency] private IEntityManager _entityManager = default!;
|
||||
|
||||
public override CompletionResult TryAutocomplete(ParserContext ctx, CommandArgument? arg)
|
||||
{
|
||||
var hint = ToolshedCommand.GetArgHint(arg, typeof(ProtoId<EntityPrototype>));
|
||||
|
||||
var artifact = _entityManager.System<SharedXenoArtifactSystem>();
|
||||
|
||||
return CompletionResult.FromHintOptions(artifact.EffectPrototypeIds, hint);
|
||||
}
|
||||
}
|
||||
|
|
@ -94,8 +94,15 @@ public abstract partial class SharedXenoArtifactSystem
|
|||
{
|
||||
var entProtoId = _entityTable.GetSpawns(ent.Comp.EffectsTable)
|
||||
.First();
|
||||
return CreateNode(ent, entProtoId, trigger, depth);
|
||||
}
|
||||
|
||||
AddNode((ent, ent), entProtoId, out var nodeEnt, dirty: false);
|
||||
/// <summary>
|
||||
/// Creates artifact node entity, attaching trigger and marking depth level for future use.
|
||||
/// </summary>
|
||||
public Entity<XenoArtifactNodeComponent> CreateNode(Entity<XenoArtifactComponent> ent, EntProtoId effect, XenoArchTriggerPrototype trigger, int depth = 0)
|
||||
{
|
||||
AddNode((ent, ent), effect, out var nodeEnt, dirty: false);
|
||||
DebugTools.Assert(nodeEnt.HasValue, "Failed to create node on artifact.");
|
||||
|
||||
var nodeComponent = nodeEnt.Value.Comp;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
using Content.Shared.Actions;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.Toolshed.TypeParsers.XenoArtifact;
|
||||
using Content.Shared.Xenoarchaeology.Artifact.Components;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
|
|
@ -20,9 +22,16 @@ public abstract partial class SharedXenoArtifactSystem : EntitySystem
|
|||
[Dependency] private SharedContainerSystem _container = default!;
|
||||
[Dependency] private SharedPopupSystem _popup = default!;
|
||||
|
||||
// TODO: https://github.com/space-wizards/space-station-14/issues/45060
|
||||
/// <summary> Cached EntProtoIds of all XenoArtifactEffect prototypes. Used for text hints. </summary>
|
||||
[Access(typeof(XenoEffectParser), Other = AccessPermissions.None)]
|
||||
public readonly HashSet<string> EffectPrototypeIds = [];
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<PrototypesReloadedEventArgs>(OnPrototypesReloaded);
|
||||
|
||||
SubscribeLocalEvent<XenoArtifactComponent, ComponentStartup>(OnStartup);
|
||||
SubscribeLocalEvent<XenoArtifactComponent, ArtifactSelfActivateEvent>(OnSelfActivate);
|
||||
|
||||
|
|
@ -30,6 +39,28 @@ public abstract partial class SharedXenoArtifactSystem : EntitySystem
|
|||
InitializeUnlock();
|
||||
InitializeXAT();
|
||||
InitializeXAE();
|
||||
|
||||
ReloadEffectCache();
|
||||
}
|
||||
|
||||
private void OnPrototypesReloaded(PrototypesReloadedEventArgs args)
|
||||
{
|
||||
if (!args.WasModified<EntityPrototype>())
|
||||
return;
|
||||
|
||||
ReloadEffectCache();
|
||||
}
|
||||
|
||||
private void ReloadEffectCache()
|
||||
{
|
||||
EffectPrototypeIds.Clear();
|
||||
|
||||
foreach (var entityPrototype in ProtoMan.EnumeratePrototypes<EntityPrototype>())
|
||||
{
|
||||
// all effect prototypes are marked as nodes, as nodes are born from those prototypes
|
||||
if (entityPrototype.HasComp<XenoArtifactNodeComponent>(Factory) && !entityPrototype.Abstract)
|
||||
EffectPrototypeIds.Add(entityPrototype.ID);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
|
|
|||
|
|
@ -1,10 +1,29 @@
|
|||
command-description-xenoartifact-list =
|
||||
List all EntityUids of spawned artifacts.
|
||||
command-description-xenoartifact-printMatrix =
|
||||
command-description-xenoartifact-printmatrix =
|
||||
Prints out matrix that displays all edges between nodes.
|
||||
command-description-xenoartifact-totalResearch =
|
||||
command-description-xenoartifact-totalresearch =
|
||||
Gets all research points that can be extracted from artifact currently.
|
||||
command-description-xenoartifact-averageResearch =
|
||||
command-description-xenoartifact-averageresearch =
|
||||
Calculates amount of research points average generated xeno artifact will output when fully activated.
|
||||
command-description-xenoartifact-unlockAllNodes =
|
||||
command-description-xenoartifact-unlockallnodes =
|
||||
Unlocks all nodes of artifact.
|
||||
|
||||
command-description-xenoartifact-createnode =
|
||||
Create node in artifact (new on depth 0 or attach next to existing one).
|
||||
command-description-xenoartifact-createnodeatdepth =
|
||||
Add a new node to the given artifact.
|
||||
command-description-xenoartifact-spawnartwithnode =
|
||||
Spawns a new xeno artifact with single node with the given trigger and effect.
|
||||
command-description-xenoartifact-unlocknode =
|
||||
Marks a node as unlocked.
|
||||
command-description-xenoartifact-removenode =
|
||||
Removes a node from a xeno artifact.
|
||||
command-description-xenoartifact-addedge =
|
||||
Adds an edge between two nodes of a xeno artifact.
|
||||
|
||||
command-spawnartifactwithnode-spawn-artifact-item-hint = use hand-held artifact
|
||||
command-spawnartifactwithnode-spawn-artifact-structure-hint = use structure-like stationary artifact
|
||||
command-spawnartifactwithnode-spawn-artifact-type-hint = <artifact entity proto id>
|
||||
|
||||
command-xenoartifact-common-node-hint = depth {$depth} node {$nodeId} trigger {$nodeDetail}
|
||||
|
|
|
|||
|
|
@ -1,4 +0,0 @@
|
|||
cmd-unlocknode-desc = Unlocks a node on a given artifact
|
||||
cmd-unlocknode-help = unlocknode <artifact uid> <node uid>
|
||||
cmd-unlocknode-artifact-hint = <artifact uid>
|
||||
cmd-unlocknode-node-hint = <node uid>
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
- type: entity
|
||||
- type: entity
|
||||
parent: [BaseItem, BaseXenoArtifact]
|
||||
id: BaseXenoArtifactItem
|
||||
name: artifact
|
||||
|
|
@ -61,6 +61,15 @@
|
|||
tableId: XenoArtifactEffectsHandheldOnlyTable
|
||||
weight: 2
|
||||
|
||||
- type: entity
|
||||
id: DummyArtifactItem
|
||||
parent: BaseXenoArtifactItem
|
||||
name: artifact
|
||||
suffix: Debug
|
||||
components:
|
||||
- type: XenoArtifact
|
||||
isGenerationRequired: false
|
||||
|
||||
- type: entity
|
||||
parent: BaseXenoArtifactItem
|
||||
id: ComplexXenoArtifactItem
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
- type: entity
|
||||
- type: entity
|
||||
parent: [BaseStructureDynamic, BaseXenoArtifact]
|
||||
id: BaseXenoArtifactStructure
|
||||
name: artifact
|
||||
|
|
@ -40,6 +40,15 @@
|
|||
mask:
|
||||
- MachineMask
|
||||
|
||||
- type: entity
|
||||
id: DummyArtifactStructure
|
||||
parent: BaseXenoArtifactStructure
|
||||
name: artifact
|
||||
suffix: Debug
|
||||
components:
|
||||
- type: XenoArtifact
|
||||
isGenerationRequired: false
|
||||
|
||||
- type: entity
|
||||
parent: BaseXenoArtifactStructure
|
||||
id: ComplexXenoArtifact
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue