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))