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

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Diagnostics;
using System.Text.Json;
using XFEEDToolBox.Core.Data;
using XFEEDToolBox.Core.Models;
using XFEEDToolBox.Core.Native;
using XFEEDToolBox.Core.Navigation;

internal static class LocalSteeringAcceptance
{
    public static async Task RunAsync(int pid,string exactName,string reportPath)
    {
        if(File.Exists(reportPath)||File.Exists(reportPath+".jsonl"))throw new IOException("Use a new report path.");
        var settings=ToolboxSettings.Load(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),"XFEstudio","XFEEDToolBox","settings.json"));
        await using var journal=new JournalMonitor(settings.JournalDirectory);await journal.StartAsync();var raw=new NavigationPipeClient(pid);
        var hash=(await raw.CallAsync(new{op="describe"})).GetProperty("gameSha256").GetString()!;
        using var source=new NativeCurrentSystemSource(pid,hash,()=>journal.State);var snapshot=await source.ReadLocationsAsync();
        var row=snapshot.Locations.Single(x=>x.Name.Equals(exactName,StringComparison.Ordinal));
        var target=new SystemNavigationTarget(snapshot.SystemAddress,row.WorldAddress,row.Name,row.MarketId is >0?SystemTargetKind.Station:SystemTargetKind.Orbit,row.MarketId)
            {NativeKey=row.Key,NativeKind=row.NativeKind,NativeIdentity=row.Identity};
        var driver=new NativeSystemFlightControlDriver(pid,hash,()=>journal.State);
        await using var log=new StreamWriter(new FileStream(reportPath+".jsonl",FileMode.CreateNew,FileAccess.Write,FileShare.Read));
        var start=DateTimeOffset.UtcNow;var clock=Stopwatch.StartNew();var reached=false;var returned=false;var released=false;var inputs=0;double maxSpeed=0,maxDisplacement=0,maxHeat=0;
        string? failure=null;
        try
        {
            using var timeout=new CancellationTokenSource(TimeSpan.FromSeconds(40));await driver.SelectAsync(target,timeout.Token);
            var first=await driver.ReadSystemFlightAsync(timeout.Token);
            if(first.Mode!=LocalFlightMode.Normal||first.Speed>=1||first.HeatPercent>=60||first.PlayerOverride||first.ExternalThreat)throw new InvalidOperationException("Local steering acceptance requires a stationary safe ship in normal space.");
            var original=first.Forward;var up=first.Up;var right=Vector3d.Cross(up,original).Unit();var offset=(original*Math.Cos(5*Math.PI/180)+right*Math.Sin(5*Math.PI/180)).Unit();DateTimeOffset? stableSince=null;
            while(clock.Elapsed<TimeSpan.FromSeconds(30))
            {
                var frame=await driver.ReadSystemFlightAsync(timeout.Token);
                maxSpeed=Math.Max(maxSpeed,frame.Speed);maxDisplacement=Math.Max(maxDisplacement,(frame.Position-first.Position).Length);maxHeat=Math.Max(maxHeat,frame.HeatPercent??0);
                if(frame.Mode!=LocalFlightMode.Normal||maxSpeed>=1||maxDisplacement>1||maxHeat>=60||frame.PlayerOverride||frame.ExternalThreat)throw new InvalidOperationException("Local steering motion/heat/state bound exceeded.");
                var direction=reached?original:offset;var error=Vector3d.AngleDegrees(frame.Forward,direction);
                var decision=new SystemFlightDecision(SystemNavigationPhase.Aligning,reached?"回到原姿态":"验证局部转向",direction,0){UpDirection=up};
                await driver.ApplySystemFlightAsync(decision,frame,target,frame.ObservedAt.AddMilliseconds(200),timeout.Token);inputs++;
                await log.WriteLineAsync(JsonSerializer.Serialize(new{at=DateTimeOffset.UtcNow,reached,error,frame,decision,inputs}));await log.FlushAsync();
                if(error<.3)stableSince??=DateTimeOffset.UtcNow;else stableSince=null;
                if(stableSince is {} since&&DateTimeOffset.UtcNow-since>TimeSpan.FromMilliseconds(500))
                {if(reached){returned=true;break;}reached=true;stableSince=null;}
                await Task.Delay(40,timeout.Token);
            }
            if(!returned)throw new TimeoutException("Local steering did not settle at the offset and original orientations.");
        }
        catch(Exception error){failure=error.ToString();}
        finally{try{await driver.ReleaseSystemFlightAsync();released=true;}catch(Exception error){failure=(failure??"")+" Release: "+error.Message;}}
        var passed=reached&&returned&&released&&failure is null;
        await File.WriteAllTextAsync(reportPath,JsonSerializer.Serialize(new{pid,start,finished=DateTimeOffset.UtcNow,passed,reached,returned,released,inputs,maxSpeed,maxDisplacement,maxHeat,failure,tradeOrdersSent=0,fsdInputsSent=0,completeNavigationAccepted=false},ToolboxSettings.JsonOptions));
        Console.WriteLine(JsonSerializer.Serialize(new{passed,reached,returned,released,inputs,maxSpeed,maxDisplacement,maxHeat,failure}));
        if(!passed)throw new InvalidOperationException("Local steering acceptance failed.");
    }
}