test: surface path timing contracts in live harness

This commit is contained in:
BruceChen 2026-04-14 10:51:13 +00:00
parent 4b193e639c
commit be6be4da36
9 changed files with 305 additions and 38 deletions

View file

@ -1763,7 +1763,8 @@ namespace MinecraftClient
pathSegmentManager = new Pathing.Execution.PathSegmentManager(
debugLog: msg => Log.Debug(msg),
infoLog: msg => Log.Info(msg));
infoLog: msg => Log.Info(msg),
observer: new Pathing.Execution.Telemetry.PathExecutionLogObserver(msg => Log.Debug(msg)));
pathSegmentManager.StartNavigation(goal, result);
string statusStr = result.Status == Pathing.Core.PathStatus.Partial ? " (partial)" : "";

View file

@ -0,0 +1,84 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using MinecraftClient.Mapping;
namespace MinecraftClient.Pathing.Execution.Telemetry
{
public sealed class PathExecutionLogObserver : IPathExecutionObserver
{
private readonly Action<string>? _debug;
public PathExecutionLogObserver(Action<string>? debug) => _debug = debug;
public void OnNavigationStarted(IReadOnlyList<PathSegment> segments) =>
_debug?.Invoke(string.Format(
CultureInfo.InvariantCulture,
Translations.pathing_metric_route_start,
segments.Count));
public void OnSegmentStarted(int segmentIndex, int totalSegments, PathSegment segment) =>
_debug?.Invoke(string.Format(
CultureInfo.InvariantCulture,
Translations.pathing_metric_segment_start,
segmentIndex,
totalSegments,
segment.MoveType,
segment.ExitTransition));
public void OnSegmentCompleted(int segmentIndex, int totalSegments, PathSegment segment, int elapsedTicks, Location position) =>
_debug?.Invoke(string.Format(
CultureInfo.InvariantCulture,
Translations.pathing_metric_segment_complete,
segmentIndex,
totalSegments,
segment.MoveType,
elapsedTicks,
position.X,
position.Y,
position.Z));
public void OnSegmentFailed(int segmentIndex, int totalSegments, PathSegment segment, int elapsedTicks, Location position) =>
_debug?.Invoke(string.Format(
CultureInfo.InvariantCulture,
Translations.pathing_metric_segment_failed,
segmentIndex,
totalSegments,
segment.MoveType,
elapsedTicks,
position.X,
position.Y,
position.Z));
public void OnNavigationCompleted(int totalTicks) =>
_debug?.Invoke(string.Format(
CultureInfo.InvariantCulture,
Translations.pathing_metric_route_complete,
totalTicks));
public void OnReplanStarted(int replanCount, Location position) =>
_debug?.Invoke(string.Format(
CultureInfo.InvariantCulture,
Translations.pathing_metric_replan_start,
replanCount,
position.X,
position.Y,
position.Z));
public void OnReplanSucceeded(int replanCount, IReadOnlyList<PathSegment> segments) =>
_debug?.Invoke(string.Format(
CultureInfo.InvariantCulture,
Translations.pathing_metric_replan_success,
replanCount,
segments.Count));
public void OnReplanFailed(int replanCount, Location position) =>
_debug?.Invoke(string.Format(
CultureInfo.InvariantCulture,
Translations.pathing_metric_replan_failed,
replanCount,
position.X,
position.Y,
position.Z));
}
}

View file

@ -3527,6 +3527,78 @@ namespace MinecraftClient {
return ResourceManager.GetString("cmd.goto.failed", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to [PathMetric] routeStart segments={0}.
/// </summary>
internal static string pathing_metric_route_start {
get {
return ResourceManager.GetString("pathing.metric.route_start", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to [PathMetric] segmentStart index={0} total={1} move={2} transition={3}.
/// </summary>
internal static string pathing_metric_segment_start {
get {
return ResourceManager.GetString("pathing.metric.segment_start", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to [PathMetric] segmentComplete index={0} total={1} move={2} ticks={3} x={4:F2} y={5:F2} z={6:F2}.
/// </summary>
internal static string pathing_metric_segment_complete {
get {
return ResourceManager.GetString("pathing.metric.segment_complete", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to [PathMetric] segmentFailed index={0} total={1} move={2} ticks={3} x={4:F2} y={5:F2} z={6:F2}.
/// </summary>
internal static string pathing_metric_segment_failed {
get {
return ResourceManager.GetString("pathing.metric.segment_failed", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to [PathMetric] routeComplete totalTicks={0}.
/// </summary>
internal static string pathing_metric_route_complete {
get {
return ResourceManager.GetString("pathing.metric.route_complete", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to [PathMetric] replanStart count={0} x={1:F2} y={2:F2} z={3:F2}.
/// </summary>
internal static string pathing_metric_replan_start {
get {
return ResourceManager.GetString("pathing.metric.replan_start", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to [PathMetric] replanSuccess count={0} segments={1}.
/// </summary>
internal static string pathing_metric_replan_success {
get {
return ResourceManager.GetString("pathing.metric.replan_success", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to [PathMetric] replanFailed count={0} x={1:F2} y={2:F2} z={3:F2}.
/// </summary>
internal static string pathing_metric_replan_failed {
get {
return ResourceManager.GetString("pathing.metric.replan_failed", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Already following {0}!.

View file

@ -1252,6 +1252,30 @@ Change EnableEmoji=false in the settings if the display is confusing.</value>
<data name="cmd.goto.failed" xml:space="preserve">
<value>No path found ({0} nodes explored in {1}ms)</value>
</data>
<data name="pathing.metric.route_start" xml:space="preserve">
<value>[PathMetric] routeStart segments={0}</value>
</data>
<data name="pathing.metric.segment_start" xml:space="preserve">
<value>[PathMetric] segmentStart index={0} total={1} move={2} transition={3}</value>
</data>
<data name="pathing.metric.segment_complete" xml:space="preserve">
<value>[PathMetric] segmentComplete index={0} total={1} move={2} ticks={3} x={4:F2} y={5:F2} z={6:F2}</value>
</data>
<data name="pathing.metric.segment_failed" xml:space="preserve">
<value>[PathMetric] segmentFailed index={0} total={1} move={2} ticks={3} x={4:F2} y={5:F2} z={6:F2}</value>
</data>
<data name="pathing.metric.route_complete" xml:space="preserve">
<value>[PathMetric] routeComplete totalTicks={0}</value>
</data>
<data name="pathing.metric.replan_start" xml:space="preserve">
<value>[PathMetric] replanStart count={0} x={1:F2} y={2:F2} z={3:F2}</value>
</data>
<data name="pathing.metric.replan_success" xml:space="preserve">
<value>[PathMetric] replanSuccess count={0} segments={1}</value>
</data>
<data name="pathing.metric.replan_failed" xml:space="preserve">
<value>[PathMetric] replanFailed count={0} x={1:F2} y={2:F2} z={3:F2}</value>
</data>
<data name="cmd.follow.already_following" xml:space="preserve">
<value>Already following {0}!</value>
</data>