Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 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
154 changes: 118 additions & 36 deletions Forge.Tests/Helpers/StatescriptTestHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,23 +45,70 @@ public static SetVariableNode CreateSetVariableNode(
node.BindOutput(SetVariableNode.TargetOutput, targetVariableName, scope);
return node;
}

public static ApplyEffectNode CreateApplyEffectNode(
StringKey effectPropertyName,
StringKey targetPropertyName,
StringKey? levelPropertyName = null,
StringKey? ownershipPropertyName = null)
{
var node = new ApplyEffectNode();
node.BindInput(ApplyEffectNode.EffectInput, effectPropertyName);
node.BindInput(ApplyEffectNode.TargetInput, targetPropertyName);

if (levelPropertyName.HasValue && levelPropertyName.Value != StringKey.Empty)
{
node.BindInput(ApplyEffectNode.LevelInput, levelPropertyName.Value);
}

if (ownershipPropertyName.HasValue && ownershipPropertyName.Value != StringKey.Empty)
{
node.BindInput(ApplyEffectNode.OwnershipInput, ownershipPropertyName.Value);
}

return node;
}

public static EffectNode CreateEffectNode(
StringKey effectPropertyName,
StringKey targetPropertyName,
StringKey? levelPropertyName = null,
StringKey? ownershipPropertyName = null)
{
var node = new EffectNode();
node.BindInput(EffectNode.EffectInput, effectPropertyName);
node.BindInput(EffectNode.TargetInput, targetPropertyName);

if (levelPropertyName.HasValue && levelPropertyName.Value != StringKey.Empty)
{
node.BindInput(EffectNode.LevelInput, levelPropertyName.Value);
}

if (ownershipPropertyName.HasValue && ownershipPropertyName.Value != StringKey.Empty)
{
node.BindInput(EffectNode.OwnershipInput, ownershipPropertyName.Value);
}

return node;
}
}

/// <summary>
/// Convenience helpers for creating ability-driven graph contexts in resolver tests.
/// </summary>
internal static class ResolverTestContextFactory
{
public static GraphContext CreateAbilityGraphContext(TestEntity entity, float magnitude = 0f)
public static GraphContext CreateAbilityGraphContext(TestEntity entity, float magnitude = 0f, int level = 1)
{
return CreateAbilityGraphContext(entity, target: null, source: null, magnitude: magnitude);
return CreateAbilityGraphContext(entity, target: null, source: null, magnitude: magnitude, level: level);
}

public static GraphContext CreateAbilityGraphContext(
TestEntity owner,
TestEntity? target,
TestEntity? source,
float magnitude = 0f)
float magnitude = 0f,
int level = 1)
{
var graph = new Graph();
var captureNode = new CaptureGraphContextNode();
Expand All @@ -74,7 +121,7 @@ public static GraphContext CreateAbilityGraphContext(
var behavior = new GraphAbilityBehavior(graph);

AbilityData abilityData = CreateAbilityData("ResolverTest", () => behavior);
AbilityHandle handle = Grant(owner, abilityData, source)
AbilityHandle handle = Grant(owner, abilityData, source, level)
?? throw new InvalidOperationException(
"Failed to grant the resolver test ability and create an ability graph context.");

Expand All @@ -94,7 +141,11 @@ public static GraphContext CreateAbilityGraphContext(
return captureNode.CapturedGraphContext;
}

public static GraphContext CreateAbilityGraphContext<TData>(TestEntity entity, TData activationData, float magnitude = 0f)
public static GraphContext CreateAbilityGraphContext<TData>(
TestEntity entity,
TData activationData,
float magnitude = 0f,
int level = 1)
{
var graph = new Graph();
var captureNode = new CaptureGraphContextNode();
Expand All @@ -107,8 +158,9 @@ public static GraphContext CreateAbilityGraphContext<TData>(TestEntity entity, T
var behavior = new GraphAbilityBehavior<TData>(graph);

AbilityData abilityData = CreateAbilityData("TypedResolverTest", () => behavior);
AbilityHandle? handle = Grant(entity, abilityData) ?? throw new InvalidOperationException(
"Failed to grant the typed resolver test ability and create an ability graph context.");
AbilityHandle? handle = Grant(entity, abilityData, sourceEntity: null, level: level)
?? throw new InvalidOperationException(
"Failed to grant the typed resolver test ability and create an ability graph context.");

if (!handle.Activate(activationData, out _, magnitude: magnitude))
{
Expand All @@ -128,22 +180,16 @@ public static GraphContext CreateAbilityGraphContext<TData>(TestEntity entity, T
}

public static void ExecuteAbilityGraph(
Graph graph,
TestEntity owner,
ActionNode actionNode,
TestEntity? target = null,
TestEntity? source = null,
float magnitude = 0f)
float magnitude = 0f,
int level = 1)
{
var graph = new Graph();

graph.AddNode(actionNode);
graph.AddConnection(new Connection(
graph.EntryNode.OutputPorts[EntryNode.OutputPort],
actionNode.InputPorts[ActionNode.InputPort]));

var behavior = new GraphAbilityBehavior(graph);
AbilityData abilityData = CreateAbilityData("ResolverExecutionTest", () => behavior);
AbilityHandle handle = Grant(owner, abilityData, source)
AbilityHandle handle = Grant(owner, abilityData, source, level)
?? throw new InvalidOperationException("Failed to grant the resolver execution test ability.");

if (!handle.Activate(out _, target, magnitude))
Expand All @@ -152,16 +198,33 @@ public static void ExecuteAbilityGraph(
}
}

private static AbilityHandle? Grant(TestEntity target, AbilityData data)
public static void ExecuteAbilityGraph(
TestEntity owner,
ActionNode actionNode,
TestEntity? target = null,
TestEntity? source = null,
float magnitude = 0f,
int level = 1)
{
return Grant(target, data, sourceEntity: null);
var graph = new Graph();

graph.AddNode(actionNode);
graph.AddConnection(new Connection(
graph.EntryNode.OutputPorts[EntryNode.OutputPort],
actionNode.InputPorts[ActionNode.InputPort]));

ExecuteAbilityGraph(graph, owner, target, source, magnitude, level);
}

private static AbilityHandle? Grant(TestEntity target, AbilityData data, IForgeEntity? sourceEntity)
private static AbilityHandle? Grant(
TestEntity target,
AbilityData data,
IForgeEntity? sourceEntity,
int level = 1)
{
var grantConfig = new GrantAbilityConfig(
data,
new ScalableInt(1),
new ScalableInt(level),
AbilityDeactivationPolicy.CancelImmediately,
AbilityDeactivationPolicy.CancelImmediately,
false,
Expand Down Expand Up @@ -283,6 +346,29 @@ protected override void Execute(GraphContext graphContext)
}
}

internal sealed class ReadPropertyNode<T> : ActionNode
where T : unmanaged
{
#pragma warning disable RCS1158 // Static member in generic type should use a type parameter
public const byte ValueInput = 0;
#pragma warning restore RCS1158 // Static member in generic type should use a type parameter

public bool Found { get; private set; }

public T LastReadValue { get; private set; }

protected override void DefineParameters(List<InputProperty> inputProperties, List<OutputVariable> outputVariables)
{
inputProperties.Add(new InputProperty("Value", typeof(T)));
}

protected override void Execute(GraphContext graphContext)
{
Found = graphContext.TryResolve(InputProperties[ValueInput].BoundName, out T value);
LastReadValue = value;
}
}

internal sealed class CaptureActivationContextNode : ActionNode
{
public object? CapturedActivationContext { get; private set; }
Expand Down Expand Up @@ -357,8 +443,7 @@ protected override void Execute(GraphContext graphContext)
}
}

internal sealed class ReadReferencePropertyNode<T> : ActionNode
where T : class
internal sealed class ReadObjectPropertyNode<T> : ActionNode
{
public T? LastReadValue { get; private set; }

Expand All @@ -369,15 +454,14 @@ protected override void DefineParameters(List<InputProperty> inputProperties, Li

protected override void Execute(GraphContext graphContext)
{
graphContext.TryResolveReference(InputProperties[0].BoundName, out T? value);
LastReadValue = value;
graphContext.TryResolveObject(InputProperties[0].BoundName, typeof(T), out object? value);
LastReadValue = value is T typedValue ? typedValue : default;
}
}

internal sealed class ReadReferenceArrayPropertyNode<T> : ActionNode
where T : class
internal sealed class ReadObjectArrayPropertyNode<T> : ActionNode
{
public T?[]? LastReadArray { get; private set; }
public T[]? LastReadArray { get; private set; }

protected override void DefineParameters(List<InputProperty> inputProperties, List<OutputVariable> outputVariables)
{
Expand All @@ -386,7 +470,7 @@ protected override void DefineParameters(List<InputProperty> inputProperties, Li

protected override void Execute(GraphContext graphContext)
{
graphContext.TryResolveReferenceArray(InputProperties[0].BoundName, out T?[]? values);
graphContext.TryResolveObjectArray(InputProperties[0].BoundName, out T[]? values);
LastReadArray = values;
}
}
Expand All @@ -403,10 +487,9 @@ protected override void Execute(GraphContext graphContext)
}
}

internal sealed class ResolveReferenceResolverNode<T>(IReferenceResolver<T> resolver) : ActionNode
where T : class
internal sealed class ResolveObjectResolverNode<T>(IObjectResolver<T> resolver) : ActionNode
{
private readonly IReferenceResolver<T> _resolver = resolver;
private readonly IObjectResolver<T> _resolver = resolver;

public T? LastResolvedValue { get; private set; }

Expand All @@ -416,12 +499,11 @@ protected override void Execute(GraphContext graphContext)
}
}

internal sealed class ResolveReferenceArrayResolverNode<T>(IReferenceArrayResolver<T> resolver) : ActionNode
where T : class
internal sealed class ResolveObjectArrayResolverNode<T>(IObjectArrayResolver<T> resolver) : ActionNode
{
private readonly IReferenceArrayResolver<T> _resolver = resolver;
private readonly IObjectArrayResolver<T> _resolver = resolver;

public T?[]? LastResolvedArray { get; private set; }
public T[]? LastResolvedArray { get; private set; }

protected override void Execute(GraphContext graphContext)
{
Expand Down
Loading
Loading