XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Text.Json;
using XFEEDToolBox.Core.Plugins;
namespace XFEEDToolBox.Core.Navigation;

public sealed partial class NativeSystemFlightControlDriver
{
    private NavigationPipeClient? dockingResetPipe;
    private string? dockingResetRequestId;
    private DateTimeOffset dockingResetDeadline;
    private bool requestOriginalDockingStart;
    private bool emptyDockingDiagnostic=true;
    public JsonElement? LastOriginalDockingResetReceipt{get;private set;}

    /// <summary>Explicit empty-ship validation retains its narrower ship/cargo limits.</summary>
    public Task EnableOriginalDockingResetTestAsync(CancellationToken token=default)=>EnableOriginalDockingResetTestAsync(false,token);
    public async Task EnableOriginalDockingResetTestAsync(bool startDockingAfterZero,CancellationToken token=default)
        =>await ConfigureOriginalDockingAsync(startDockingAfterZero,true,token);
    public async Task ConfigureOriginalDockingControlAsync(string packageDirectory,CancellationToken token=default)
    {
        var native=new NavigationPipeClient(processId,OriginalDockingService);
        try{await native.CallAsync(new{op="describe"},token);}
        catch(Exception error)when(!token.IsCancellationRequested&&error is IOException or OperationCanceledException)
        {
            var main=await pipe.CallAsync(new{op="describe"},token);
            if(main.GetProperty("processId").GetInt32()!=processId||main.GetProperty("gameSha256").GetString()!=gameHash)
                throw new InvalidDataException("Original docking package belongs to another game.");
            await RuntimeInteractionModule.LoadAsync(processId,gameHash,main.GetProperty("owningThread").GetInt32(),packageDirectory,token);
        }
        await ConfigureOriginalDockingAsync(true,false,token);
    }
    private async Task ConfigureOriginalDockingAsync(bool startDockingAfterZero,bool diagnostic,CancellationToken token)
    {
        if(dockingResetRequestId is not null)throw new InvalidOperationException("An original docking test request is already immutable.");
        const string service=OriginalDockingService;
        var candidate=new NavigationPipeClient(processId,service);var hello=await candidate.CallAsync(new{op="describe"},token);
        if(hello.GetProperty("processId").GetInt32()!=processId||hello.GetProperty("gameSha256").GetString()!=gameHash
            ||hello.GetProperty("service").GetString()!=service||!Flag(hello,"nativeDockingReset")||!Flag(hello,"enabled")
            ||hello.GetProperty("owningThread").GetInt32()<=0||hello.GetProperty("state").GetString()!="InGame"||hello.GetProperty("nextState").GetString()!="InGame"
            ||DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()-hello.GetProperty("observedAtUnixMilliseconds").GetInt64() is <0 or >200
            ||startDockingAfterZero&&!Flag(hello,"nativeDockingStart"))
            throw new NotSupportedException("Verified original docking reset test extension is not loaded.");
        dockingResetPipe=candidate;requestOriginalDockingStart=startDockingAfterZero;emptyDockingDiagnostic=diagnostic;
    }
    private void AdoptOriginalResetReceipt(JsonElement value)
    {
        if(value.GetProperty("requestId").GetString()!=dockingResetRequestId)throw new InvalidDataException("Original reset receipt identity differs.");
        if(value.TryGetProperty("nativeGeneration",out var selectedGeneration)&&selectedGeneration.ValueKind==JsonValueKind.Number&&selectedGeneration.GetInt64()>0)
            generation=selectedGeneration.GetInt64();
        LastOriginalDockingResetReceipt=value.Clone();
    }
    private async Task OriginalDockingResetAsync(SystemFlightFrame frame,DateTimeOffset deadline,CancellationToken token)
    {
        var service=dockingResetPipe??throw new InvalidOperationException("Original docking reset is not configured.");
        if(frame.Mode!=LocalFlightMode.Normal||frame.PlayerOverride||frame.ExternalThreat||selected is null||frame.Clearance?.Allows(selected,DateTimeOffset.UtcNow)!=true
            ||frame.TargetDistance>7500||player().CurrentShipId is null
            ||emptyDockingDiagnostic&&(player().CargoCount!=0||player().CurrentShipId!=5||player().CargoCapacity!=192))
            throw new InvalidOperationException("Original reset requires the same selected main ship, current ATC and the configured validation scope.");
        if(dockingResetRequestId is not null)
        {
            if(LastOriginalDockingResetReceipt is {} prior&&Flag(prior,"applied")
                &&LastTelemetry is {} current&&NativeSystemFlightObservation.DockingInputZeroConfirmed(current))return;
            throw new InvalidOperationException("This docking grant already used its one original reset attempt; it will not be replayed.");
        }
        if(ensureFlightProtection is not null)await ensureFlightProtection(token);
        await pipe.CallAsync(new{op="local.axes.release",owner,generation},token);
        var remaining=(int)Math.Floor((deadline-DateTimeOffset.UtcNow).TotalMilliseconds);
        if(remaining is <1 or >250)throw new FlightTelemetryUnavailableException("Original reset intent frame is expired.");
        dockingResetRequestId=Guid.NewGuid().ToString("N");dockingResetDeadline=deadline;
        try
        {
            var receipt=await service.CallAsync(new{op="docking.reset.arm",requestId=dockingResetRequestId,owner,generation,
                sequence=frame.Sequence,marketId=selected.MarketId,ttlMilliseconds=remaining,expiresAtUnixMilliseconds=deadline.ToUnixTimeMilliseconds(),startDockingAfterZero=requestOriginalDockingStart},token);
            AdoptOriginalResetReceipt(receipt);
        }
        catch(Exception original)when(original is IOException or InvalidOperationException or OperationCanceledException)
        {
            // Resolve an uncertain acknowledgement by the same immutable ID;
            // arm is never sent again, even if a native reselect already happened.
            JsonElement reconciled;
            try
            {
                using var reconciliation=new CancellationTokenSource(TimeSpan.FromMilliseconds(500));
                reconciled=await service.CallAsync(new{op="docking.reset.status",requestId=dockingResetRequestId,owner},reconciliation.Token);
            }
            catch(Exception status)when(!emptyDockingDiagnostic&&!token.IsCancellationRequested
                &&(NavigationRecovery.CanRetry(status,CancellationToken.None)||status is InvalidOperationException&&status.Message=="No matching original reset request"))
            {throw new DockingResetObservationPendingException(dockingResetRequestId,selected.MarketId!.Value,frame.ObservedAt,new AggregateException(original,status));}
            catch(Exception status){throw new InvalidOperationException("Original reset outcome is unknown; the arm request was not replayed.",new AggregateException(original,status));}
            AdoptOriginalResetReceipt(reconciled);
        }
        while(true)
        {
            token.ThrowIfCancellationRequested();var receipt=LastOriginalDockingResetReceipt!.Value;
            if(Flag(receipt,"failed")||Flag(receipt,"expired"))
            {
                var error=new InvalidOperationException("Original reset was rejected: "+(receipt.TryGetProperty("issue",out var issue)?issue.GetString():"no detail"));
                if(!emptyDockingDiagnostic&&DockingValidationProof.RejectedBeforeResetDispatch(receipt))
                    throw new DockingResetObservationPendingException(dockingResetRequestId,selected.MarketId!.Value,frame.ObservedAt,error);
                throw error;
            }
            if(Flag(receipt,"applied"))
            {
                if(!DockingValidationProof.OriginalResetZero(receipt,frame.ShipEntity,selected.MarketId!.Value,frame.ObservedAt,DateTimeOffset.UtcNow))
                    throw new InvalidDataException("Original reset did not verify the selected main ship's actual accumulator and source zero.");
                if(!requestOriginalDockingStart)return;
                if(!Flag(receipt,"dockingStartRequested"))throw new InvalidDataException("Explicit original docking start was not accepted by the pinned test extension.");
                if(receipt.TryGetProperty("dockingStartFailure",out var startFailure)&&startFailure.ValueKind==JsonValueKind.String&&!string.IsNullOrEmpty(startFailure.GetString()))
                    throw new InvalidOperationException("Original docking start was rejected: "+startFailure.GetString());
                if(Flag(receipt,"originalDockingStartCalled"))return;
                // A status read can overlap the one original native call.
                // Reconcile that same request until its original deadline;
                // neither an in-progress call nor an unknown reply is retried.
            }
            if(DateTimeOffset.UtcNow>deadline.AddMilliseconds(350))throw new InvalidOperationException("Original reset receipt remains unresolved; no request will be replayed.");
            await Task.Delay(10,token);
            AdoptOriginalResetReceipt(await service.CallAsync(new{op="docking.reset.status",requestId=dockingResetRequestId,owner},token));
        }
    }
    private async Task CancelOriginalDockingResetAsync()
    {
        if(dockingResetPipe is null||dockingResetRequestId is null)return;
        try{AdoptOriginalResetReceipt(await dockingResetPipe.CallAsync(new{op="docking.reset.cancel",requestId=dockingResetRequestId,owner}));}
        catch
        {
            // The extension enforces this original absolute deadline. Waiting
            // it out does not extend the input or create a replacement request.
            var remaining=dockingResetDeadline-DateTimeOffset.UtcNow;if(remaining>TimeSpan.Zero)await Task.Delay(remaining);
        }
    }
}