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

XFEEDToolBox

【WinUI】XFE精英危险工具箱

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

internal static class LocalTargetSelection
{
    public static async Task RunAsync(int pid,string exactName,string reportPath)
    {
        if(File.Exists(reportPath))throw new IOException("Use a new report path.");
        using var timeout=new CancellationTokenSource(TimeSpan.FromSeconds(15));var token=timeout.Token;
        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 pipe=new NavigationPipeClient(pid);var hello=await pipe.CallAsync(new{op="describe"},token);var owner=Guid.NewGuid().ToString("N");
        using var source=new NativeCurrentSystemSource(pid,hello.GetProperty("gameSha256").GetString()!,()=>journal.State);
        var before=await source.ReadLocationsAsync(token);var target=before.Locations.Single(x=>x.Name.Equals(exactName,StringComparison.Ordinal));
        JsonElement selection=JsonSerializer.SerializeToElement<object?>(null),telemetry=selection;CurrentSystemSnapshot? after=null;var selected=false;string? failure=null;
        try
        {
            selection=await pipe.CallAsync(new{op="local.select",owner,key=target.Key,bodyAddress=target.WorldAddress.ToString(CultureInfo.InvariantCulture),kind=target.NativeKind,
                marketId=target.MarketId??uint.MaxValue,name=target.Name},token);
            var generation=selection.GetProperty("generation").GetInt64();var wait=Stopwatch.StartNew();
            while(!selection.GetProperty("selected").GetBoolean())
            {
                if(!selection.GetProperty("pending").GetBoolean()||wait.Elapsed>TimeSpan.FromSeconds(2))throw new InvalidOperationException("Original local target selection did not confirm.");
                await Task.Delay(30,token);selection=await pipe.CallAsync(new{op="local.status",owner,generation},token);
            }
            await Task.Delay(100,token);telemetry=await pipe.CallAsync(new{op="local.read"},token);after=await source.ReadLocationsAsync(token);
            var row=after.Locations.Single(x=>x.Selected);
            selected=row.Identity==target.Identity&&telemetry.GetProperty("target").GetProperty("name").GetString()==target.Name
                &&telemetry.GetProperty("target").GetProperty("bodyAddress").GetString()==target.WorldAddress.ToString(CultureInfo.InvariantCulture)
                &&telemetry.GetProperty("target").GetProperty("key").GetInt32()==target.Key
                &&row.DistanceMetres is {} distance&&Math.Abs(telemetry.GetProperty("distanceMetres").GetDouble()-distance)<Math.Max(10,distance*.0001);
            if(!selected)throw new InvalidDataException("Selected target or independently read distance differs.");
        }
        catch(Exception error){failure=error.ToString();}
        finally{await pipe.CallAsync(new{op="release",owner},CancellationToken.None);}
        await File.WriteAllTextAsync(reportPath,JsonSerializer.Serialize(new{pid,target,selection,telemetry,independentSelection=after?.Locations.FirstOrDefault(x=>x.Selected),selected,failure,flightInputsSent=0},ToolboxSettings.JsonOptions));
        Console.WriteLine(JsonSerializer.Serialize(new{selected,target.Name,target.DistanceMetres,failure,reportPath,flightInputsSent=0}));
        if(!selected)throw new InvalidOperationException("Local target acceptance failed; inspect report.");
    }
}