try graph???
This commit is contained in:
@@ -1,3 +1,6 @@
|
||||
using Content.Shared._CP14.MagicRituals.Requirements;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server._CP14.MagicRituals.Components;
|
||||
|
||||
/// <summary>
|
||||
@@ -11,4 +14,7 @@ public sealed partial class CP14MagicRitualPhaseComponent : Component
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public Entity<CP14MagicRitualComponent>? Ritual;
|
||||
|
||||
[DataField(required: true)]
|
||||
public Dictionary<EntProtoId, List<CP14RitualRequirement>> Requirements = new();
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._CP14.MagicRitual;
|
||||
@@ -0,0 +1,14 @@
|
||||
using Content.Shared._CP14.MagicRituals.Requirements;
|
||||
|
||||
namespace Content.Shared._CP14.MagicRituals.Graph;
|
||||
|
||||
[Serializable]
|
||||
[DataDefinition]
|
||||
public sealed partial class CP14RitualGraphEdge
|
||||
{
|
||||
[DataField("to", required:true)]
|
||||
public string Target { get; private set; } = string.Empty;
|
||||
|
||||
[DataField]
|
||||
public CP14RitualRequirement[] Requirements = Array.Empty<CP14RitualRequirement>();
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._CP14.MagicRituals.Graph;
|
||||
|
||||
[Serializable]
|
||||
[DataDefinition]
|
||||
public sealed partial class CP14RitualGraphNode
|
||||
{
|
||||
[DataField("node", required: true)]
|
||||
public string Name { get; private set; } = default!;
|
||||
|
||||
[DataField(serverOnly: true)]
|
||||
public EntProtoId Entity { get; private set; }
|
||||
|
||||
[DataField]
|
||||
public CP14RitualGraphEdge[] Edges = Array.Empty<CP14RitualGraphEdge>();
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._CP14.MagicRituals.Graph;
|
||||
|
||||
[Prototype("ritualGraph")]
|
||||
public sealed partial class CP14RitualGraphPrototype : IPrototype
|
||||
{
|
||||
private readonly Dictionary<string, CP14RitualGraphNode> _nodes = new();
|
||||
private readonly Dictionary<(string, string), CP14RitualGraphNode[]?> _paths = new();
|
||||
private readonly Dictionary<string, Dictionary<CP14RitualGraphNode, CP14RitualGraphNode?>> _pathfinding = new();
|
||||
|
||||
[ViewVariables]
|
||||
[IdDataField]
|
||||
public string ID { get; private set; } = default!;
|
||||
|
||||
[DataField]
|
||||
public string? Start { get; private set; }
|
||||
|
||||
[DataField]
|
||||
public List<CP14RitualGraphNode> Graph = new();
|
||||
|
||||
public bool TryPath(string startNode, string finishNode, [NotNullWhen(true)] out CP14RitualGraphNode[]? path)
|
||||
{
|
||||
return (path = Path(startNode, finishNode)) != null;
|
||||
}
|
||||
|
||||
public string[]? PathId(string startNode, string finishNode)
|
||||
{
|
||||
if (Path(startNode, finishNode) is not {} path)
|
||||
return null;
|
||||
|
||||
var nodes = new string[path.Length];
|
||||
|
||||
for (var i = 0; i < path.Length; i++)
|
||||
{
|
||||
nodes[i] = path[i].Name;
|
||||
}
|
||||
|
||||
return nodes;
|
||||
}
|
||||
|
||||
public CP14RitualGraphNode[]? Path(string startNode, string finishNode)
|
||||
{
|
||||
var tuple = (startNode, finishNode);
|
||||
|
||||
if (_paths.ContainsKey(tuple))
|
||||
return _paths[tuple];
|
||||
|
||||
// Get graph given the current start.
|
||||
|
||||
Dictionary<CP14RitualGraphNode, CP14RitualGraphNode?> 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<CP14RitualGraphNode>();
|
||||
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<CP14RitualGraphNode, CP14RitualGraphNode?> PathsForStart(string start)
|
||||
{
|
||||
// TODO: Make this use A* or something, although it's not that important.
|
||||
var startNode = _nodes[start];
|
||||
|
||||
var frontier = new Queue<CP14RitualGraphNode>();
|
||||
var cameFrom = new Dictionary<CP14RitualGraphNode, CP14RitualGraphNode?>();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace Content.Shared._CP14.MagicRituals.Requirements;
|
||||
|
||||
[ImplicitDataDefinitionForInheritors]
|
||||
[MeansImplicitUse]
|
||||
public abstract partial class CP14RitualRequirement
|
||||
{
|
||||
public abstract void Check(EntityManager entManager);
|
||||
}
|
||||
@@ -1,13 +1,9 @@
|
||||
using Content.Shared.Stacks;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server._CP14.MagicRituals.Components.Requirements;
|
||||
namespace Content.Shared._CP14.MagicRituals.Requirements;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[RegisterComponent, Access(typeof(CP14RitualSystem))]
|
||||
public sealed partial class CP14RitualRequirementEntitiesComponent : Component
|
||||
public sealed partial class EntitiesRequirement : CP14RitualRequirement
|
||||
{
|
||||
[DataField]
|
||||
public float CheckRange = 1f;
|
||||
@@ -26,4 +22,9 @@ public sealed partial class CP14RitualRequirementEntitiesComponent : Component
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public EntProtoId? VisualEffect = "CP14DustEffect";
|
||||
|
||||
public override void Check(EntityManager entManager)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user