using XFEEDToolBox.Core.Models;
using XFEEDToolBox.Core.Navigation;
using XFEEDToolBox.Core.Session;
namespace XFEEDToolBox.Core.Execution;
/// <summary>Trade entry into the same flight coordinator used by both navigation pages.</summary>
public sealed class NativeTradeNavigation(int processId,string gameHash,Func<PlayerState> player,string pluginDirectory,
Func<double> fuelReserve,Func<CancellationToken,Task> ensureProtection,FlightAutomationCoordinator? flightAutomation=null,Action<System.Text.Json.JsonElement>? cruiseDiagnostics=null,
Func<decimal>? serviceReserveCredits=null)
{
private readonly FlightAutomationCoordinator flights=flightAutomation??new(player);
public bool FlightSafetyActive=>flights.ActiveEntry==FlightAutomationEntry.Trade&&flights.IsControllingFlight;
public event Action<string>? Status;
public event Action<NativeWalletObservation>? WalletObserved;
public event Action<ConfirmedDockedServiceReceipt>? ServiceConfirmed;
private NativeTradePauseRecovery? pauseRecovery;
public IDisposable EnterRunningMenuRecovery(Func<bool> isRunning,CancellationToken token)
{
if(pauseRecovery is null)
{
pauseRecovery=new(processId,gameHash,player,Path.Combine(pluginDirectory,"DockingControl"));
pauseRecovery.Status+=message=>Status?.Invoke(message);
}
return pauseRecovery.EnterRunningMenuRecovery(isRunning,token);
}
public async Task TravelAsync(Station destination,Func<CancellationToken,Task> beforeInput,CancellationToken token)
{
var adapter=new NativeFlightJourneyDriver(processId,gameHash,player,pluginDirectory,fuelReserve,ensureProtection,beforeInput,cruiseDiagnostics,
serviceReserveCredits:serviceReserveCredits,walletObserved:value=>WalletObserved?.Invoke(value),serviceConfirmed:value=>ServiceConfirmed?.Invoke(value));
void Report(FlightAutomationProgress value){if(value.Entry==FlightAutomationEntry.Trade)Status?.Invoke(value.Message);}
void Galaxy(NavigationProgress value)=>Status?.Invoke(value.Message);
void Local(SystemNavigationProgress value)=>Status?.Invoke(value.Message);
flights.Progress+=Report;flights.Interstellar.Progress+=Galaxy;flights.Local.Progress+=Local;adapter.Status+=message=>Status?.Invoke(message);
try
{
var result=await flights.TravelToStationAsync(destination,adapter,token);
if(result.HandoffFailed)throw new DockingHandoffException(result.Failure?.Message??"原生自动降落交接未完成。",destination.MarketId,result.Failure);
// Preserve the typed recovery signal consumed by the trade engine.
result.RequireCompleted(token);
}
finally{flights.Progress-=Report;flights.Interstellar.Progress-=Galaxy;flights.Local.Progress-=Local;}
}
}
using XFEEDToolBox.Core.Models;
using XFEEDToolBox.Core.Navigation;
using XFEEDToolBox.Core.Session;
namespace XFEEDToolBox.Core.Execution;
/// <summary>Trade entry into the same flight coordinator used by both navigation pages.</summary>
public sealed class NativeTradeNavigation(int processId,string gameHash,Func<PlayerState> player,string pluginDirectory,
Func<double> fuelReserve,Func<CancellationToken,Task> ensureProtection,FlightAutomationCoordinator? flightAutomation=null,Action<System.Text.Json.JsonElement>? cruiseDiagnostics=null,
Func<decimal>? serviceReserveCredits=null)
{
private readonly FlightAutomationCoordinator flights=flightAutomation??new(player);
public bool FlightSafetyActive=>flights.ActiveEntry==FlightAutomationEntry.Trade&&flights.IsControllingFlight;
public event Action<string>? Status;
public event Action<NativeWalletObservation>? WalletObserved;
public event Action<ConfirmedDockedServiceReceipt>? ServiceConfirmed;
private NativeTradePauseRecovery? pauseRecovery;
public IDisposable EnterRunningMenuRecovery(Func<bool> isRunning,CancellationToken token)
{
if(pauseRecovery is null)
{
pauseRecovery=new(processId,gameHash,player,Path.Combine(pluginDirectory,"DockingControl"));
pauseRecovery.Status+=message=>Status?.Invoke(message);
}
return pauseRecovery.EnterRunningMenuRecovery(isRunning,token);
}
public async Task TravelAsync(Station destination,Func<CancellationToken,Task> beforeInput,CancellationToken token)
{
var adapter=new NativeFlightJourneyDriver(processId,gameHash,player,pluginDirectory,fuelReserve,ensureProtection,beforeInput,cruiseDiagnostics,
serviceReserveCredits:serviceReserveCredits,walletObserved:value=>WalletObserved?.Invoke(value),serviceConfirmed:value=>ServiceConfirmed?.Invoke(value));
void Report(FlightAutomationProgress value){if(value.Entry==FlightAutomationEntry.Trade)Status?.Invoke(value.Message);}
void Galaxy(NavigationProgress value)=>Status?.Invoke(value.Message);
void Local(SystemNavigationProgress value)=>Status?.Invoke(value.Message);
flights.Progress+=Report;flights.Interstellar.Progress+=Galaxy;flights.Local.Progress+=Local;adapter.Status+=message=>Status?.Invoke(message);
try
{
var result=await flights.TravelToStationAsync(destination,adapter,token);
if(result.HandoffFailed)throw new DockingHandoffException(result.Failure?.Message??"原生自动降落交接未完成。",destination.MarketId,result.Failure);
// Preserve the typed recovery signal consumed by the trade engine.
result.RequireCompleted(token);
}
finally{flights.Progress-=Report;flights.Interstellar.Progress-=Galaxy;flights.Local.Progress-=Local;}
}
}