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 System.Text.Json.Nodes;
using XFEEDToolBox.Core.Data;
using XFEEDToolBox.Core.Models;
using XFEEDToolBox.Core.Navigation;

// Data replay only. Never selects targets, leases controls, or installs a DLL.
internal static class ReferencePreview
{
    public static async Task RunAsync(int pid,string geometryPath,string reportPath)
    {
        if(File.Exists(reportPath))throw new IOException("Use a new reference preview report path.");
        using var source=JsonDocument.Parse(await File.ReadAllTextAsync(geometryPath));var data=source.RootElement;
        if(data.GetProperty("pid").GetInt32()!=pid||DateTimeOffset.UtcNow-data.GetProperty("observedAt").GetDateTimeOffset()>TimeSpan.FromSeconds(30))throw new InvalidDataException("Reference replay requires a fresh snapshot of the selected process.");
        using var game=Process.GetProcessById(pid);var start=game.StartTime;
        var pipe=new NavigationPipeClient(pid);var hello=await pipe.CallAsync(new{op="describe"});var raw=await pipe.CallAsync(new{op="read"});
        if(hello.GetProperty("gameSha256").GetString()!=data.GetProperty("gameSha256").GetString()||raw.GetProperty("entityId").GetString()!=data.GetProperty("entityId").GetString())throw new InvalidDataException("Reference replay process/build/entity changed.");
        Vector3d V(JsonElement array)=>new(array[0].GetDouble(),array[1].GetDouble(),array[2].GetDouble());
        if((V(raw.GetProperty("position"))-V(data.GetProperty("rawPosition"))).Length>1)throw new InvalidDataException("Player moved between reference and telemetry observations.");
        var directory=Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),"Saved Games","Frontier Developments","Elite Dangerous");
        await using var journal=new JournalMonitor(directory);await journal.StartAsync();var player=journal.State;
        if(player.Navigation.CurrentSystemAddress.ToString()!=data.GetProperty("system").GetString())throw new InvalidDataException("Journal and replay reference disagree.");
        var position=V(data.GetProperty("shipMatrix")[3]);var bodies=data.GetProperty("bodies").EnumerateArray().ToArray();
        var primary=bodies.Where(b=>b.GetProperty("kind").GetInt32()==1).MinBy(b=>(position-V(b.GetProperty("matrix")[3])).Length);
        var origin=V(primary.GetProperty("matrix")[3]);
        object Array(Vector3d value)=>new[]{value.X,value.Y,value.Z};
        var geometry=new{fresh=true,referenceFrameVerified=true,referenceBodyKind=data.GetProperty("referenceBodyKind").GetInt32(),
            worldAddress=data.GetProperty("referenceWorldAddress").GetString(),bodyAddress=primary.GetProperty("address").GetString(),bodyKind=1,starType=primary.GetProperty("starType").GetInt32(),
            exclusionRadius=primary.GetProperty("exclusionRadius").GetDouble(),position=Array(position-origin),
            right=data.GetProperty("shipMatrix")[0],up=data.GetProperty("shipMatrix")[1],forward=data.GetProperty("shipMatrix")[2],
            nearbyBodies=bodies.Select(b=>new{bodyAddress=b.GetProperty("address").GetString(),bodyKind=b.GetProperty("kind").GetInt32(),starType=b.GetProperty("starType"),
                exclusionRadius=b.GetProperty("exclusionRadius").GetDouble(),centre=Array(V(b.GetProperty("matrix")[3])-origin)}).ToArray()};
        var node=JsonNode.Parse(raw.GetRawText())!;node["referenceWorldAddress"]=data.GetProperty("referenceWorldAddress").GetString();
        node["geometry"]=JsonSerializer.SerializeToNode(geometry,ToolboxSettings.JsonOptions);
        using var replay=JsonDocument.Parse(node.ToJsonString());var now=DateTimeOffset.UtcNow;
        var target=long.Parse(raw.GetProperty("fsd").GetProperty("targetAddress").GetString()!);
        var next=player.Navigation.Route.FirstOrDefault(w=>w.SystemAddress==target)??throw new InvalidDataException("Actual target is not on the Journal route.");
        var observation=new NativeFrameProjector(data.GetProperty("gameSha256").GetString()!).Project(replay.RootElement,player,next,.5,now);
        var frame=observation.Frame;var decision=new FlightNavigator().Decide(frame,next,observation.Thermal,now);
        if(game.HasExited||game.StartTime!=start)throw new InvalidOperationException("Selected process changed.");
        await File.WriteAllTextAsync(reportPath,JsonSerializer.Serialize(new{processId=pid,loadedPlugin=hello.GetProperty("version").GetString(),
            source="VM_READ orbital matrices replayed through the managed projector; no replacement native DLL loaded",system=player.SystemName,next=next.Name,
            referenceKind=data.GetProperty("referenceBodyKind").GetInt32(),frame.Position,frame.InSupercruise,frame.SpeedMetresPerSecond,frame.OutwardDepartureRequired,
            frame.FuelMain,frame.FuelNeededToNextRefuel,frame.HeatPercent,frame.NativeFullChargePeak,bodies=bodies.Length,
            blockingBodies=frame.Obstacles.Append(frame.CurrentStar!).Where(b=>FlightGeometry.Obscures(b,frame.Position,frame.TargetPosition)).Select(b=>b.BodyId).ToArray(),
            decision,referenceReplay=true,flightCommandsInvoked=false,gameRestartInvoked=false,screenUse=false,gameNativeFunctionsInvoked=false},new JsonSerializerOptions{WriteIndented=true}));
        Console.WriteLine(await File.ReadAllTextAsync(reportPath));
    }
}