Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 130 additions & 0 deletions Forge.Tests/Statescript/GraphProcessorTests.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright © Gamesmiths Guild.

using FluentAssertions;
using Gamesmiths.Forge.Effects;
using Gamesmiths.Forge.Effects.Duration;
using Gamesmiths.Forge.Statescript;
using Gamesmiths.Forge.Statescript.Nodes;
using Gamesmiths.Forge.Statescript.Nodes.State;
Expand Down Expand Up @@ -996,4 +998,132 @@ public void ValidatePropertyType_checks_array_property_type()
definitions.ValidatePropertyType("ids", typeof(double[])).Should().BeFalse();
definitions.ValidatePropertyType("ids", typeof(int[])).Should().BeTrue();
}

[Fact]
[Trait("Graph", "Resolve")]
public void TryResolve_uses_the_first_of_two_properties_sharing_a_name()
{
var graph = new Graph();
graph.VariableDefinitions.DefineProperty(
"value",
new VariantResolver(new Variant128(11.0), typeof(double)));
graph.VariableDefinitions.DefineProperty(
"value",
new VariantResolver(new Variant128(22.0), typeof(double)));

var node = new ReadPropertyNode<double>();
node.BindInput(ReadPropertyNode<double>.ValueInput, "value");
graph.AddNode(node);
graph.AddConnection(new Connection(
graph.EntryNode.OutputPorts[EntryNode.OutputPort],
node.InputPorts[ActionNode.InputPort]));

var processor = new GraphProcessor(graph);
processor.StartGraph();

node.Found.Should().BeTrue();
node.LastReadValue.Should().Be(11.0);
}

[Fact]
[Trait("Graph", "Resolve")]
public void TryResolveArray_uses_the_first_of_two_array_properties_sharing_a_name()
{
var graph = new Graph();
graph.VariableDefinitions.DefineArrayProperty(
"ids",
new TestArrayPropertyResolver(typeof(int), [[new Variant128(1), new Variant128(2)]]));
graph.VariableDefinitions.DefineArrayProperty(
"ids",
new TestArrayPropertyResolver(typeof(int), [[new Variant128(9)]]));

var node = new ReadArrayPropertyNode();
node.BindInput(ReadArrayPropertyNode.InputArray, "ids");
graph.AddNode(node);
graph.AddConnection(new Connection(
graph.EntryNode.OutputPorts[EntryNode.OutputPort],
node.InputPorts[ActionNode.InputPort]));

var processor = new GraphProcessor(graph);
processor.StartGraph();

node.LastReadArray.Should().BeEquivalentTo([new Variant128(1), new Variant128(2)]);
}

[Fact]
[Trait("Graph", "Resolve")]
public void TryResolveObject_uses_the_first_of_two_object_properties_sharing_a_name()
{
var firstData = new EffectData("First", new DurationData(DurationType.Instant));
var secondData = new EffectData("Second", new DurationData(DurationType.Instant));

var graph = new Graph();
graph.VariableDefinitions.DefineObjectProperty("effect", new EffectFromDataResolver(firstData));
graph.VariableDefinitions.DefineObjectProperty("effect", new EffectFromDataResolver(secondData));

var node = new ReadObjectPropertyNode<Effect>();
node.BindInput(0, "effect");
graph.AddNode(node);
graph.AddConnection(new Connection(
graph.EntryNode.OutputPorts[EntryNode.OutputPort],
node.InputPorts[ActionNode.InputPort]));

var processor = new GraphProcessor(graph);
processor.StartGraph();

node.LastReadValue.Should().NotBeNull();
node.LastReadValue!.EffectData.Name.Should().Be(firstData.Name);
}

[Fact]
[Trait("Graph", "Resolve")]
public void TryResolveObjectArray_uses_the_first_of_two_object_array_properties_sharing_a_name()
{
var firstData = new EffectData("First", new DurationData(DurationType.Instant));
var secondData = new EffectData("Second", new DurationData(DurationType.Instant));

var graph = new Graph();
graph.VariableDefinitions.DefineObjectArrayProperty(
"effects",
new EffectArrayFromDataResolver([firstData]));
graph.VariableDefinitions.DefineObjectArrayProperty(
"effects",
new EffectArrayFromDataResolver([secondData]));

var node = new ReadObjectArrayPropertyNode<Effect>();
node.BindInput(0, "effects");
graph.AddNode(node);
graph.AddConnection(new Connection(
graph.EntryNode.OutputPorts[EntryNode.OutputPort],
node.InputPorts[ActionNode.InputPort]));

var processor = new GraphProcessor(graph);
processor.StartGraph();

node.LastReadArray.Should().ContainSingle();
node.LastReadArray![0].EffectData.Name.Should().Be(firstData.Name);
}

[Fact]
[Trait("Graph", "Resolve")]
public void TryResolve_reports_a_name_that_is_neither_a_variable_nor_a_property()
{
var graph = new Graph();
graph.VariableDefinitions.DefineProperty(
"defined",
new VariantResolver(new Variant128(1.0), typeof(double)));

var node = new ReadPropertyNode<double>();
node.BindInput(ReadPropertyNode<double>.ValueInput, "missing");
graph.AddNode(node);
graph.AddConnection(new Connection(
graph.EntryNode.OutputPorts[EntryNode.OutputPort],
node.InputPorts[ActionNode.InputPort]));

var processor = new GraphProcessor(graph);
processor.StartGraph();

node.ExecutionCount.Should().Be(1);
node.Found.Should().BeFalse();
}
}
134 changes: 57 additions & 77 deletions Forge/Statescript/GraphContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -125,14 +125,11 @@ public bool TryResolve<T>(StringKey name, out T value)
return false;
}

foreach (PropertyDefinition definition in Processor.Graph.VariableDefinitions.PropertyDefinitions)
if (Processor.Graph.VariableDefinitions.PropertiesByName.TryGetValue(name, out PropertyDefinition definition))
{
if (definition.Name == name)
{
Variant128 resolved = definition.Resolver.Resolve(this);
value = resolved.Get<T>();
return true;
}
Variant128 resolved = definition.Resolver.Resolve(this);
value = resolved.Get<T>();
return true;
}

return false;
Expand All @@ -157,13 +154,10 @@ public bool TryResolveVariant(StringKey name, out Variant128 value)
return false;
}

foreach (PropertyDefinition definition in Processor.Graph.VariableDefinitions.PropertyDefinitions)
if (Processor.Graph.VariableDefinitions.PropertiesByName.TryGetValue(name, out PropertyDefinition definition))
{
if (definition.Name == name)
{
value = definition.Resolver.Resolve(this);
return true;
}
value = definition.Resolver.Resolve(this);
return true;
}

return false;
Expand Down Expand Up @@ -191,17 +185,13 @@ public bool TryResolveArray(StringKey name, [NotNullWhen(true)] out Variant128[]
return true;
}

if (Processor is not null)
if (Processor is not null
&& Processor.Graph.VariableDefinitions.ArrayPropertiesByName.TryGetValue(
name,
out ArrayPropertyDefinition definition))
{
foreach (ArrayPropertyDefinition definition in
Processor.Graph.VariableDefinitions.ArrayPropertyDefinitions)
{
if (definition.Name == name)
{
values = definition.Resolver.ResolveArray(this);
return true;
}
}
values = definition.Resolver.ResolveArray(this);
return true;
}

values = null;
Expand Down Expand Up @@ -230,19 +220,18 @@ public bool TryResolveObject<T>(StringKey name, [MaybeNullWhen(false)] out T val
return false;
}

foreach (ObjectPropertyDefinition definition in Processor.Graph.VariableDefinitions.ObjectPropertyDefinitions)
if (Processor.Graph.VariableDefinitions.ObjectPropertiesByName.TryGetValue(
name,
out ObjectPropertyDefinition definition))
{
if (definition.Name == name)
if (!typeof(T).IsAssignableFrom(definition.Resolver.ValueType))
{
if (!typeof(T).IsAssignableFrom(definition.Resolver.ValueType))
{
value = default!;
return false;
}

value = (T)definition.Resolver.Resolve(this)!;
return true;
value = default!;
return false;
}

value = (T)definition.Resolver.Resolve(this)!;
return true;
}

value = default!;
Expand Down Expand Up @@ -271,19 +260,18 @@ public bool TryResolveObject(StringKey name, Type expectedType, out object? valu
return false;
}

foreach (ObjectPropertyDefinition definition in Processor.Graph.VariableDefinitions.ObjectPropertyDefinitions)
if (Processor.Graph.VariableDefinitions.ObjectPropertiesByName.TryGetValue(
name,
out ObjectPropertyDefinition definition))
{
if (definition.Name == name)
if (!expectedType.IsAssignableFrom(definition.Resolver.ValueType))
{
if (!expectedType.IsAssignableFrom(definition.Resolver.ValueType))
{
value = null;
return false;
}

value = definition.Resolver.Resolve(this);
return true;
value = null;
return false;
}

value = definition.Resolver.Resolve(this);
return true;
}

value = null;
Expand All @@ -306,29 +294,25 @@ public bool TryResolveObjectArray<T>(StringKey name, [NotNullWhen(true)] out T[]
return true;
}

if (Processor is not null)
if (Processor is not null
&& Processor.Graph.VariableDefinitions.ObjectArrayPropertiesByName.TryGetValue(
name,
out ObjectArrayPropertyDefinition definition))
{
foreach (ObjectArrayPropertyDefinition definition in
Processor.Graph.VariableDefinitions.ObjectArrayPropertyDefinitions)
if (!typeof(T).IsAssignableFrom(definition.Resolver.ElementType))
{
values = null;
return false;
}

object?[] resolved = definition.Resolver.ResolveArray(this);
values = new T[resolved.Length];
for (int i = 0; i < resolved.Length; i++)
{
if (definition.Name == name)
{
if (!typeof(T).IsAssignableFrom(definition.Resolver.ElementType))
{
values = null;
return false;
}

object?[] resolved = definition.Resolver.ResolveArray(this);
values = new T[resolved.Length];
for (int i = 0; i < resolved.Length; i++)
{
values[i] = (T)resolved[i]!;
}

return true;
}
values[i] = (T)resolved[i]!;
}

return true;
}

values = null;
Expand All @@ -354,23 +338,19 @@ public bool TryResolveObjectArray(
return true;
}

if (Processor is not null)
if (Processor is not null
&& Processor.Graph.VariableDefinitions.ObjectArrayPropertiesByName.TryGetValue(
name,
out ObjectArrayPropertyDefinition definition))
{
foreach (ObjectArrayPropertyDefinition definition in
Processor.Graph.VariableDefinitions.ObjectArrayPropertyDefinitions)
if (!expectedElementType.IsAssignableFrom(definition.Resolver.ElementType))
{
if (definition.Name == name)
{
if (!expectedElementType.IsAssignableFrom(definition.Resolver.ElementType))
{
values = null;
return false;
}

values = definition.Resolver.ResolveArray(this);
return true;
}
values = null;
return false;
}

values = definition.Resolver.ResolveArray(this);
return true;
}

values = null;
Expand Down
Loading
Loading