From 380bb89f83206b14b7815b186ea73c235039085d Mon Sep 17 00:00:00 2001
From: Vera Aguilera Puerto <6766154+Zumorica@users.noreply.github.com>
Date: Fri, 25 Mar 2022 05:00:39 +0100
Subject: [PATCH] Documents more ConstructionSystem methods. (#7246)
---
.../Construction/ConstructionSystem.Graph.cs | 129 +++++++++++++++++-
.../Construction/ConstructionSystem.Guided.cs | 8 ++
.../ConstructionSystem.Interactions.cs | 44 +++++-
.../ConstructionSystem.Pathfinding.cs | 29 ++++
4 files changed, 201 insertions(+), 9 deletions(-)
diff --git a/Content.Server/Construction/ConstructionSystem.Graph.cs b/Content.Server/Construction/ConstructionSystem.Graph.cs
index 21fbd560bd..317f844583 100644
--- a/Content.Server/Construction/ConstructionSystem.Graph.cs
+++ b/Content.Server/Construction/ConstructionSystem.Graph.cs
@@ -18,6 +18,15 @@ namespace Content.Server.Construction
{
}
+ ///
+ /// Sets a container on an entity as being handled by Construction. This essentially means that it will
+ /// be transferred if the entity prototype changes.
+ ///
+ /// The target entity.
+ /// The container identifier. This method does not check whether the container exists.
+ /// The construction component of the target entity. Will be resolved if null.
+ /// Whether we could set the container as being handled by construction or not. Also returns false if
+ /// the entity does not have a .
public bool AddContainer(EntityUid uid, string container, ConstructionComponent? construction = null)
{
if (!Resolve(uid, ref construction))
@@ -26,14 +35,32 @@ namespace Content.Server.Construction
return construction.Containers.Add(container);
}
+ ///
+ /// Gets the current construction graph of an entity, or null.
+ ///
+ /// The target entity.
+ /// The construction component of the target entity. Will be resolved if null.
+ /// The current construction graph of an entity or null if invalid. Also returns null if the entity
+ /// does not have a .
+ /// An entity with a valid construction state will always have a valid graph.
public ConstructionGraphPrototype? GetCurrentGraph(EntityUid uid, ConstructionComponent? construction = null)
{
if (!Resolve(uid, ref construction, false))
return null;
+ // If the set graph prototype does not exist, also return null. This could be due to admemes changing values
+ // in ViewVariables, so even though the construction state is invalid, just return null.
return _prototypeManager.TryIndex(construction.Graph, out ConstructionGraphPrototype? graph) ? graph : null;
}
+ ///
+ /// Gets the construction graph node the entity is currently at, or null.
+ ///
+ /// The target entity.
+ /// The construction component of the target entity. Will be resolved if null.
+ /// The current construction graph node the entity is currently at, or null if invalid. Also returns
+ /// null if the entity does not have a .
+ /// An entity with a valid construction state will always be at a valid node.
public ConstructionGraphNode? GetCurrentNode(EntityUid uid, ConstructionComponent? construction = null)
{
if (!Resolve(uid, ref construction, false))
@@ -45,6 +72,14 @@ namespace Content.Server.Construction
return GetCurrentGraph(uid, construction) is not {} graph ? null : GetNodeFromGraph(graph, nodeIdentifier);
}
+ ///
+ /// Gets the construction graph edge the entity is currently at, or null.
+ ///
+ /// The target entity.
+ /// The construction component of the target entity. Will be resolved if null.
+ /// The construction graph edge the entity is currently at, if any. Also returns null if the entity
+ /// does not have a .
+ /// An entity with a valid construction state might not always be at an edge.
public ConstructionGraphEdge? GetCurrentEdge(EntityUid uid, ConstructionComponent? construction = null)
{
if (!Resolve(uid, ref construction, false))
@@ -56,6 +91,14 @@ namespace Content.Server.Construction
return GetCurrentNode(uid, construction) is not {} node ? null : GetEdgeFromNode(node, edgeIndex);
}
+ ///
+ /// Gets the construction graph step the entity is currently at, or null.
+ ///
+ /// The target entity.
+ /// The construction component of the target entity. Will be resolved if null.
+ /// The construction graph step the entity is currently at, if any. Also returns null if the entity
+ /// does not have a .
+ /// An entity with a valid construction state might not always be at a step or an edge.
public ConstructionGraphStep? GetCurrentStep(EntityUid uid, ConstructionComponent? construction = null)
{
if (!Resolve(uid, ref construction, false))
@@ -67,6 +110,15 @@ namespace Content.Server.Construction
return GetStepFromEdge(edge, construction.StepIndex);
}
+ ///
+ /// Gets the construction graph node the entity's construction pathfinding is currently targeting, if any.
+ ///
+ /// The target entity.
+ /// The construction component of the target entity. Will be resolved if null.
+ /// The construction graph node the entity's construction pathfinding is currently targeting, or null
+ /// if it's not currently targeting any node. Also returns null if the entity does not have a
+ /// .
+ /// Target nodes are entirely optional and only used for pathfinding purposes.
public ConstructionGraphNode? GetTargetNode(EntityUid uid, ConstructionComponent? construction)
{
if (!Resolve(uid, ref construction))
@@ -81,6 +133,16 @@ namespace Content.Server.Construction
return GetNodeFromGraph(graph, targetNodeId);
}
+ ///
+ /// Gets the construction graph edge the entity's construction pathfinding is currently targeting, if any.
+ ///
+ /// The target entity.
+ /// The construction component of the target entity. Will be resolved if null.
+ /// The construction graph edge the entity's construction pathfinding is currently targeting, or null
+ /// if it's not currently targeting any edge. Also returns null if the entity does not have a
+ /// .
+ /// Target edges are entirely optional and only used for pathfinding purposes. The targeted edge will
+ /// be an edge on the current construction node the entity is at.
public ConstructionGraphEdge? GetTargetEdge(EntityUid uid, ConstructionComponent? construction)
{
if (!Resolve(uid, ref construction))
@@ -95,6 +157,13 @@ namespace Content.Server.Construction
return GetEdgeFromNode(node, targetEdgeIndex);
}
+ ///
+ /// Gets both the construction edge and step the entity is currently at, if any.
+ ///
+ /// The target entity.
+ /// The construction component of the target entity. Will be resolved if null.
+ /// A tuple containing the current edge and step the entity's construction state is at.
+ /// The edge, step or both could be null. A valid construction state does not necessarily need them.
public (ConstructionGraphEdge? edge, ConstructionGraphStep? step) GetCurrentEdgeAndStep(EntityUid uid,
ConstructionComponent? construction = null)
{
@@ -111,21 +180,49 @@ namespace Content.Server.Construction
return (edge, step);
}
+ ///
+ /// Gets a node from a construction graph given its identifier.
+ ///
+ /// The construction graph where to get the node.
+ /// The identifier that corresponds to the node.
+ /// The node that corresponds to the identifier, or null if it doesn't exist.
public ConstructionGraphNode? GetNodeFromGraph(ConstructionGraphPrototype graph, string id)
{
return graph.Nodes.TryGetValue(id, out var node) ? node : null;
}
+ ///
+ /// Gets an edge from a construction node given its index.
+ ///
+ /// The construction node where to get the edge.
+ /// The index or position of the edge on the node.
+ /// The edge on that index in the construction node, or null if none.
public ConstructionGraphEdge? GetEdgeFromNode(ConstructionGraphNode node, int index)
{
return node.Edges.Count > index ? node.Edges[index] : null;
}
+ ///
+ /// Gets a step from a construction edge given its index.
+ ///
+ /// The construction edge where to get the step.
+ /// The index or position of the step on the edge.
+ /// The edge on that index in the construction edge, or null if none.
public ConstructionGraphStep? GetStepFromEdge(ConstructionGraphEdge edge, int index)
{
return edge.Steps.Count > index ? edge.Steps[index] : null;
}
+ ///
+ /// Performs a node change on a construction entity, optionally performing the actions for the new node.
+ ///
+ /// The target entity.
+ /// An optional user entity, for actions.
+ /// The identifier of the node to change to.
+ /// Whether the actions for the new node will be performed or not.
+ /// The construction component of the target entity. Will be resolved if null.
+ /// Whether the node change succeeded or not. Also returns false if the entity does not have a .
+ /// This method also updates the construction pathfinding automatically, if the node change succeeds.
public bool ChangeNode(EntityUid uid, EntityUid? userUid, string id, bool performActions = true, ConstructionComponent? construction = null)
{
if (!Resolve(uid, ref construction))
@@ -152,6 +249,20 @@ namespace Content.Server.Construction
return true;
}
+ ///
+ /// Performs an entity prototype change on a construction entity.
+ /// The old entity will be removed, and a new one will be spawned in its place. Some values will be kept,
+ /// and any containers handled by construction will be transferred to the new entity as well.
+ ///
+ /// The target entity.
+ /// An optional user entity, for actions.
+ /// The entity prototype identifier for the new entity.
+ /// The construction component of the target entity. Will be resolved if null.
+ /// The metadata component of the target entity. Will be resolved if null.
+ /// The transform component of the target entity. Will be resolved if null.
+ /// The container manager component of the target entity. Will be resolved if null,
+ /// but it is an optional component and not required for the method to work.
+ /// The new entity, or null if the method did not succeed.
private EntityUid? ChangeEntity(EntityUid uid, EntityUid? userUid, string newEntity,
ConstructionComponent? construction = null,
MetaDataComponent? metaData = null,
@@ -189,7 +300,7 @@ namespace Content.Server.Construction
}
// Transform transferring.
- var newTransform = EntityManager.GetComponent(newUid);
+ var newTransform = Transform(newUid);
newTransform.LocalRotation = transform.LocalRotation;
newTransform.Anchored = transform.Anchored;
@@ -217,7 +328,7 @@ namespace Content.Server.Construction
}
}
- EntityManager.QueueDeleteEntity(uid);
+ QueueDel(uid);
if(GetCurrentNode(newUid, newConstruction) is {} node)
PerformActions(newUid, userUid, node.Actions);
@@ -225,6 +336,18 @@ namespace Content.Server.Construction
return newUid;
}
+ ///
+ /// Performs a construction graph change on a construction entity, also changing the node to a valid one on
+ /// the new graph.
+ ///
+ /// The target entity.
+ /// An optional user entity, for actions.
+ /// The identifier for the construction graph to switch to.
+ /// The identifier for a node on the new construction graph to switch to.
+ /// Whether actions on the new node will be performed or not.
+ /// The construction component of the target entity. Will be resolved if null.
+ /// Whether the construction graph change succeeded or not. Returns false if the entity does not have
+ /// a .
public bool ChangeGraph(EntityUid uid, EntityUid? userUid, string graphId, string nodeId, bool performActions = true, ConstructionComponent? construction = null)
{
if (!Resolve(uid, ref construction))
@@ -233,7 +356,7 @@ namespace Content.Server.Construction
if (!_prototypeManager.TryIndex(graphId, out var graph))
return false;
- if(GetNodeFromGraph(graph, nodeId) is not {} node)
+ if(GetNodeFromGraph(graph, nodeId) is not {})
return false;
construction.Graph = graphId;
diff --git a/Content.Server/Construction/ConstructionSystem.Guided.cs b/Content.Server/Construction/ConstructionSystem.Guided.cs
index 8071e8915f..cdb822a7b1 100644
--- a/Content.Server/Construction/ConstructionSystem.Guided.cs
+++ b/Content.Server/Construction/ConstructionSystem.Guided.cs
@@ -102,6 +102,14 @@ namespace Content.Server.Construction
}
+ ///
+ /// Returns a for a given ,
+ /// generating and caching it as needed.
+ ///
+ /// The construction prototype to generate the guide for. We must be able to pathfind
+ /// from its starting node to its ending node to be able to generate a guide for it.
+ /// The guide for the given construction, or null if we can't pathfind from the start node to the
+ /// end node on that construction.
private ConstructionGuide? GetGuide(ConstructionPrototype construction)
{
// NOTE: This method might be allocate a fair bit, but do not worry!
diff --git a/Content.Server/Construction/ConstructionSystem.Interactions.cs b/Content.Server/Construction/ConstructionSystem.Interactions.cs
index 3b7f670644..3de9809b6e 100644
--- a/Content.Server/Construction/ConstructionSystem.Interactions.cs
+++ b/Content.Server/Construction/ConstructionSystem.Interactions.cs
@@ -312,7 +312,7 @@ namespace Content.Server.Construction
// we split the stack in two and insert the split stack.
if (insertStep is MaterialConstructionGraphStep materialInsertStep)
{
- if (_stackSystem.Split(insert, materialInsertStep.Amount, EntityManager.GetComponent(interactUsing.User).Coordinates) is not {} stack)
+ if (_stackSystem.Split(insert, materialInsertStep.Amount, Transform(interactUsing.User).Coordinates) is not {} stack)
return HandleResult.False;
insert = stack;
@@ -334,7 +334,7 @@ namespace Content.Server.Construction
else
{
// If we don't store the item in a container on the entity, we just delete it right away.
- EntityManager.DeleteEntity(insert);
+ Del(insert);
}
// Step has been handled correctly, so we signal this.
@@ -387,6 +387,13 @@ namespace Content.Server.Construction
return HandleResult.False;
}
+ ///
+ /// Checks whether a number of s are true for a given entity.
+ ///
+ /// The entity to pass to the conditions.
+ /// The conditions to evaluate.
+ /// This method is short-circuiting; if a condition evaluates to false, we stop checking the rest of conditions.
+ /// Whether all conditions evaluate to true for the given entity.
public bool CheckConditions(EntityUid uid, IEnumerable conditions)
{
foreach (var condition in conditions)
@@ -398,11 +405,19 @@ namespace Content.Server.Construction
return true;
}
+ ///
+ /// Performs a number of s for a given entity, with an optional user entity.
+ ///
+ /// The entity to perform the actions on.
+ /// An optional user entity to pass into the actions.
+ /// The actions to perform.
+ /// This method checks whether the given target entity exists before performing any actions.
+ /// If the entity is deleted by an action, it will short-circuit and stop performing the rest of actions.
public void PerformActions(EntityUid uid, EntityUid? userUid, IEnumerable actions)
{
foreach (var action in actions)
{
- // If an action deletes the entity, we stop performing actions.
+ // If an action deletes the entity, we stop performing the rest of actions.
if (!Exists(uid))
break;
@@ -410,6 +425,12 @@ namespace Content.Server.Construction
}
}
+ ///
+ /// Resets the current construction edge status on an entity.
+ ///
+ /// The target entity.
+ /// The construction component. If null, it will be resolved on the entity.
+ /// This method updates the construction pathfinding on the entity automatically.
public void ResetEdge(EntityUid uid, ConstructionComponent? construction = null)
{
if (!Resolve(uid, ref construction))
@@ -419,6 +440,7 @@ namespace Content.Server.Construction
construction.EdgeIndex = null;
construction.StepIndex = 0;
+ // Update pathfinding to keep it in sync with the current construction status.
UpdatePathfinding(uid, construction);
}
@@ -430,7 +452,7 @@ namespace Content.Server.Construction
foreach (var uid in _constructionUpdateQueue)
{
// Ensure the entity exists and has a Construction component.
- if (!EntityManager.EntityExists(uid) || !EntityManager.TryGetComponent(uid, out ConstructionComponent? construction))
+ if (!Exists(uid) || !TryComp(uid, out ConstructionComponent? construction))
continue;
// Handle all queued interactions!
@@ -446,6 +468,16 @@ namespace Content.Server.Construction
#region Event Handlers
+ ///
+ /// Queues a directed event to be handled by construction on the next update tick.
+ /// Used as a handler for any events that construction can listen to.
+ ///
+ /// The entity the event is directed to.
+ /// The construction component to queue the event on.
+ /// The directed event to be queued.
+ /// Events inheriting are treated specially by this method.
+ /// They will only be queued if they can be validated against the current construction state,
+ /// in which case they will also be set as handled.
private void EnqueueEvent(EntityUid uid, ConstructionComponent construction, object args)
{
// Handled events get treated specially.
@@ -473,7 +505,7 @@ namespace Content.Server.Construction
private void OnDoAfterComplete(ConstructionDoAfterComplete ev)
{
// Make extra sure the target entity exists...
- if (!EntityManager.EntityExists(ev.TargetUid))
+ if (!Exists(ev.TargetUid))
return;
// Re-raise this event, but directed on the target UID.
@@ -483,7 +515,7 @@ namespace Content.Server.Construction
private void OnDoAfterCancelled(ConstructionDoAfterCancelled ev)
{
// Make extra sure the target entity exists...
- if (!EntityManager.EntityExists(ev.TargetUid))
+ if (!Exists(ev.TargetUid))
return;
// Re-raise this event, but directed on the target UID.
diff --git a/Content.Server/Construction/ConstructionSystem.Pathfinding.cs b/Content.Server/Construction/ConstructionSystem.Pathfinding.cs
index 840c2778cd..988d822fdd 100644
--- a/Content.Server/Construction/ConstructionSystem.Pathfinding.cs
+++ b/Content.Server/Construction/ConstructionSystem.Pathfinding.cs
@@ -8,6 +8,13 @@ namespace Content.Server.Construction
{
public sealed partial class ConstructionSystem
{
+ ///
+ /// Sets or clears a pathfinding target node for a given construction entity.
+ ///
+ /// The target entity.
+ /// The target node to pathfind, or null to clear the current pathfinding node.
+ /// The construction component of the target entity. Will be resolved if null.
+ /// Whether we could set/clear the pathfinding target node.
public bool SetPathfindingTarget(EntityUid uid, string? targetNodeId, ConstructionComponent? construction = null)
{
if (!Resolve(uid, ref construction))
@@ -34,6 +41,12 @@ namespace Content.Server.Construction
return UpdatePathfinding(uid, graph, node, targetNode, GetCurrentEdge(uid, construction), construction);
}
+ ///
+ /// Updates the pathfinding state for the current construction state of an entity.
+ ///
+ /// The target entity.
+ /// The construction component of the target entity. Will be resolved if null.
+ /// Whether we could update the pathfinding state correctly.
public bool UpdatePathfinding(EntityUid uid, ConstructionComponent? construction = null)
{
if (!Resolve(uid, ref construction))
@@ -50,6 +63,17 @@ namespace Content.Server.Construction
return UpdatePathfinding(uid, graph, node, targetNode, GetCurrentEdge(uid, construction), construction);
}
+ ///
+ /// Internal version of , which expects a valid construction state and
+ /// actually performs the pathfinding update logic.
+ ///
+ /// The target entity.
+ /// The construction graph the entity is at.
+ /// The current construction node the entity is at.
+ /// The target node we are trying to reach on the graph.
+ /// The current edge the entity is at, or null if none.
+ /// The construction component of the target entity. Will be resolved if null.
+ /// Whether we could update the pathfinding state correctly.
private bool UpdatePathfinding(EntityUid uid, ConstructionGraphPrototype graph,
ConstructionGraphNode currentNode, ConstructionGraphNode targetNode,
ConstructionGraphEdge? currentEdge,
@@ -111,6 +135,11 @@ namespace Content.Server.Construction
return true;
}
+ ///
+ /// Clears the pathfinding targets on a construction entity.
+ ///
+ /// The target entity.
+ /// The construction component of the target entity. Will be resolved if null.
public void ClearPathfinding(EntityUid uid, ConstructionComponent? construction = null)
{
if (!Resolve(uid, ref construction))