Upgradeable machines. (#2675)

* Start work on upgradeable machines.

* Upgradeable machines work

* Component requirements for upgradeable machines

* Better container handling

* Remember to not push submodule updates in your PRs, kids!

* Refresh parts after building a machine.

* NetSync false

* Address some reviews, fix some bugs

* Nullable stackhelpers dependencies

* Use container helper method to delete all entities in containers

* Nullable string in AddContainer

* Better examine for machine frame and construction in general

* Machine breakage

* Nullable node

* nullable GraphPrototype

* Re-save saltern for autolathe parts

* Fix SaveLoadSave
This commit is contained in:
Vera Aguilera Puerto
2020-12-03 22:49:00 +01:00
committed by GitHub
parent ba2bdec13b
commit c3341132c5
36 changed files with 5270 additions and 3703 deletions

View File

@@ -48,10 +48,10 @@ namespace Content.Server.GameObjects.Components.Construction
private ConstructionGraphNode? _target = null;
[ViewVariables]
public ConstructionGraphPrototype GraphPrototype { get; private set; } = null!;
public ConstructionGraphPrototype? GraphPrototype { get; private set; }
[ViewVariables]
public ConstructionGraphNode Node { get; private set; } = null!;
public ConstructionGraphNode? Node { get; private set; } = null;
[ViewVariables]
public ConstructionGraphEdge? Edge { get; private set; } = null;
@@ -88,6 +88,17 @@ namespace Content.Server.GameObjects.Components.Construction
serializer.DataField(ref _startingNodeIdentifier, "node", string.Empty);
}
/// <summary>
/// Attempts to set a new pathfinding target.
/// </summary>
public void SetNewTarget(string node)
{
if (GraphPrototype != null && GraphPrototype.Nodes.TryGetValue(node, out var target))
{
Target = target;
}
}
public void ClearTarget()
{
_target = null;
@@ -97,8 +108,8 @@ namespace Content.Server.GameObjects.Components.Construction
public void UpdateTarget()
{
// Can't pathfind without a target.
if (Target == null) return;
// Can't pathfind without a target or no node.
if (Target == null || Node == null || GraphPrototype == null) return;
// If we're at our target, stop pathfinding.
if (Target == Node)
@@ -133,7 +144,7 @@ namespace Content.Server.GameObjects.Components.Construction
}
// Let's set the next target edge.
if (Edge == null && TargetNextEdge == null)
if (Edge == null && TargetNextEdge == null && TargetPathfinding != null)
TargetNextEdge = Node.GetEdge(TargetPathfinding.Peek().Name);
}
@@ -161,6 +172,8 @@ namespace Content.Server.GameObjects.Components.Construction
{
EdgeStep = 0;
if (Node == null || GraphPrototype == null) return false;
foreach (var edge in Node.Edges)
{
if(edge.Steps.Count == 0)
@@ -344,7 +357,7 @@ namespace Content.Server.GameObjects.Components.Construction
private async Task<bool> HandleCompletion(ConstructionGraphEdge edge, IEntity user)
{
if (edge.Steps.Count != EdgeStep)
if (edge.Steps.Count != EdgeStep || GraphPrototype == null)
{
return false;
}
@@ -380,6 +393,16 @@ namespace Content.Server.GameObjects.Components.Construction
return true;
}
public void ResetEdge()
{
_edgeNestedStepProgress = null;
TargetNextEdge = null;
Edge = null;
EdgeStep = 0;
UpdateTarget();
}
private async Task<bool> HandleEdge(InteractUsingEventArgs eventArgs)
{
if (Edge == null || EdgeStep >= Edge.Steps.Count) return false;
@@ -389,7 +412,8 @@ namespace Content.Server.GameObjects.Components.Construction
private async Task<bool> HandleEntityChange(ConstructionGraphNode node, IEntity? user = null)
{
if (node.Entity == Owner.Prototype?.ID || string.IsNullOrEmpty(node.Entity)) return false;
if (node.Entity == Owner.Prototype?.ID || string.IsNullOrEmpty(node.Entity)
|| GraphPrototype == null) return false;
var entity = Owner.EntityManager.SpawnEntity(node.Entity, Owner.Transform.Coordinates);
@@ -398,7 +422,7 @@ namespace Content.Server.GameObjects.Components.Construction
if (entity.TryGetComponent(out ConstructionComponent? construction))
{
if(construction.GraphPrototype != GraphPrototype)
throw new Exception($"New entity {node.Entity}'s graph {construction.GraphPrototype.ID} isn't the same as our graph {GraphPrototype.ID} on node {node.Name}!");
throw new Exception($"New entity {node.Entity}'s graph {construction.GraphPrototype?.ID ?? null} isn't the same as our graph {GraphPrototype.ID} on node {node.Name}!");
construction.Node = node;
construction.Target = Target;
@@ -461,14 +485,6 @@ namespace Content.Server.GameObjects.Components.Construction
if (GraphPrototype.Nodes.TryGetValue(_startingNodeIdentifier, out var node))
{
Node = node;
foreach (var action in Node.Actions)
{
action.PerformAction(Owner, null);
if (Owner.Deleted)
return;
}
}
else
{
@@ -481,8 +497,25 @@ namespace Content.Server.GameObjects.Components.Construction
}
}
protected override void Startup()
{
base.Startup();
if (Node == null) return;
foreach (var action in Node.Actions)
{
action.PerformAction(Owner, null);
if (Owner.Deleted)
return;
}
}
public async Task ChangeNode(string node)
{
if (GraphPrototype == null) return;
var graphNode = GraphPrototype.Nodes[node];
if (_handling && _handlingTask?.Task != null)
@@ -508,21 +541,28 @@ namespace Content.Server.GameObjects.Components.Construction
if (Edge == null && TargetNextEdge != null)
{
var preventStepExamine = false;
foreach (var condition in TargetNextEdge.Conditions)
{
condition.DoExamine(Owner, message, inDetailsRange);
preventStepExamine |= condition.DoExamine(Owner, message, inDetailsRange);
}
TargetNextEdge.Steps[0].DoExamine(message, inDetailsRange);
if(!preventStepExamine)
TargetNextEdge.Steps[0].DoExamine(message, inDetailsRange);
return;
}
if (Edge != null)
{
var preventStepExamine = false;
foreach (var condition in Edge.Conditions)
{
condition.DoExamine(Owner, message, inDetailsRange);
preventStepExamine |= condition.DoExamine(Owner, message, inDetailsRange);
}
if (preventStepExamine) return;
}
if (_edgeNestedStepProgress == null)