Re-organize all projects (#4166)

This commit is contained in:
DrSmugleaf
2021-06-09 22:19:39 +02:00
committed by GitHub
parent 9f50e4061b
commit ff1a2d97ea
1773 changed files with 5258 additions and 5508 deletions

View File

@@ -0,0 +1,137 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables;
namespace Content.Shared.Construction.Prototypes
{
[Prototype("constructionGraph")]
public class ConstructionGraphPrototype : IPrototype, ISerializationHooks
{
private readonly Dictionary<string, ConstructionGraphNode> _nodes = new();
private readonly Dictionary<ValueTuple<string, string>, ConstructionGraphNode[]?> _paths = new();
private readonly Dictionary<string, Dictionary<ConstructionGraphNode, ConstructionGraphNode?>> _pathfinding = new();
[ViewVariables]
[DataField("id", required: true)]
public string ID { get; } = default!;
[ViewVariables]
[DataField("start")]
public string? Start { get; }
[DataField("graph", priority: 0)]
private List<ConstructionGraphNode> _graph = new();
[ViewVariables]
public IReadOnlyDictionary<string, ConstructionGraphNode> Nodes => _nodes;
void ISerializationHooks.AfterDeserialization()
{
_nodes.Clear();
foreach (var graphNode in _graph)
{
if (string.IsNullOrEmpty(graphNode.Name))
{
throw new InvalidDataException($"Name of graph node is null in construction graph {ID}!");
}
_nodes[graphNode.Name] = graphNode;
}
if (string.IsNullOrEmpty(Start) || !_nodes.ContainsKey(Start))
throw new InvalidDataException($"Starting node for construction graph {ID} is null, empty or invalid!");
}
public ConstructionGraphEdge? Edge(string startNode, string nextNode)
{
var start = _nodes[startNode];
return start.GetEdge(nextNode);
}
public bool TryPath(string startNode, string finishNode, [NotNullWhen(true)] out ConstructionGraphNode[]? path)
{
return (path = Path(startNode, finishNode)) != null;
}
public ConstructionGraphNode[]? Path(string startNode, string finishNode)
{
var tuple = new ValueTuple<string, string>(startNode, finishNode);
if (_paths.ContainsKey(tuple))
return _paths[tuple];
// Get graph given the current start.
Dictionary<ConstructionGraphNode, ConstructionGraphNode?> pathfindingForStart;
if (_pathfinding.ContainsKey(startNode))
{
pathfindingForStart = _pathfinding[startNode];
}
else
{
pathfindingForStart = _pathfinding[startNode] = PathsForStart(startNode);
}
// Follow the chain backwards.
var start = _nodes[startNode];
var finish = _nodes[finishNode];
var current = finish;
var path = new List<ConstructionGraphNode>();
while (current != start)
{
// No path.
if (current == null || !pathfindingForStart.ContainsKey(current))
{
// We remember this for next time.
_paths[tuple] = null;
return null;
}
path.Add(current);
current = pathfindingForStart[current];
}
path.Reverse();
return _paths[tuple] = path.ToArray();
}
/// <summary>
/// Uses breadth first search for pathfinding.
/// </summary>
/// <param name="start"></param>
private Dictionary<ConstructionGraphNode, ConstructionGraphNode?> PathsForStart(string start)
{
// TODO: Make this use A* or something, although it's not that important.
var startNode = _nodes[start];
var frontier = new Queue<ConstructionGraphNode>();
var cameFrom = new Dictionary<ConstructionGraphNode, ConstructionGraphNode?>();
frontier.Enqueue(startNode);
cameFrom[startNode] = null;
while (frontier.Count != 0)
{
var current = frontier.Dequeue();
foreach (var edge in current.Edges)
{
var edgeNode = _nodes[edge.Target];
if(cameFrom.ContainsKey(edgeNode)) continue;
frontier.Enqueue(edgeNode);
cameFrom[edgeNode] = current;
}
}
return cameFrom;
}
}
}

View File

@@ -0,0 +1,84 @@
#nullable enable
using System.Collections.Generic;
using Content.Shared.Construction.Conditions;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.Utility;
using Robust.Shared.ViewVariables;
namespace Content.Shared.Construction.Prototypes
{
[Prototype("construction")]
public class ConstructionPrototype : IPrototype
{
[DataField("conditions")] private List<IConstructionCondition> _conditions = new();
/// <summary>
/// Friendly name displayed in the construction GUI.
/// </summary>
[DataField("name")]
public string Name { get; } = string.Empty;
/// <summary>
/// "Useful" description displayed in the construction GUI.
/// </summary>
[DataField("description")]
public string Description { get; } = string.Empty;
/// <summary>
/// The <see cref="ConstructionGraphPrototype"/> this construction will be using.
/// </summary>
[DataField("graph")]
public string Graph { get; } = string.Empty;
/// <summary>
/// The target <see cref="ConstructionGraphNode"/> this construction will guide the user to.
/// </summary>
[DataField("targetNode")]
public string TargetNode { get; } = string.Empty;
/// <summary>
/// The starting <see cref="ConstructionGraphNode"/> this construction will start at.
/// </summary>
[DataField("startNode")]
public string StartNode { get; } = string.Empty;
/// <summary>
/// Texture path inside the construction GUI.
/// </summary>
[DataField("icon")]
public SpriteSpecifier Icon { get; } = SpriteSpecifier.Invalid;
/// <summary>
/// If you can start building or complete steps on impassable terrain.
/// </summary>
[DataField("canBuildInImpassable")]
public bool CanBuildInImpassable { get; private set; }
[DataField("category")] public string Category { get; private set; } = string.Empty;
[DataField("objectType")] public ConstructionType Type { get; private set; } = ConstructionType.Structure;
[ViewVariables]
[DataField("id", required: true)]
public string ID { get; } = default!;
[DataField("placementMode")]
public string PlacementMode { get; } = "PlaceFree";
/// <summary>
/// Whether this construction can be constructed rotated or not.
/// </summary>
[DataField("canRotate")]
public bool CanRotate { get; } = true;
public IReadOnlyList<IConstructionCondition> Conditions => _conditions;
}
public enum ConstructionType
{
Structure,
Item,
}
}