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

internal static class NativeRepairAcceptance
{
    public static async Task RunAsync(int pid,string address,string action,string path)
    {
        if(action is not("repair" or "integrity")||File.Exists(path)||File.Exists(path+".submitted.json"))throw new ArgumentException("A new bounded repair acceptance is required.");
        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 initial=journal.State;
        if(!initial.InGame||!initial.Docked||initial.MarketId is not {} market||initial.CurrentShipId!=7||!initial.StationServicesKnown||!initial.StationServices.Contains("repair"))throw new InvalidOperationException("Actual docked acceptance ship and repair service required.");
        using var stop=new CancellationTokenSource(TimeSpan.FromSeconds(100));
        await using var protection=await FlightTestProtectionScope.ArmAsync(pid);var pipe=new NavigationPipeClient(pid);
        async Task<JsonElement> Wait(JsonElement queued)
        {
            var generation=queued.GetProperty("generation").GetUInt64();
            while(true){var value=await pipe.CallAsync(new{op="commerce.market.status",generation},stop.Token);if(value.GetProperty("state").GetInt32()>=3)return value;await Task.Delay(80,stop.Token);}
        }
        Task<JsonElement> Prices()=>ReadPrices();
        async Task<JsonElement> ReadPrices()=>await Wait(await pipe.CallAsync(new{op="station.services.inspect",marketId=(uint)market,maintenanceAddress=address},stop.Token));
        var key=Guid.NewGuid().ToString("N");var started=DateTimeOffset.UtcNow;string? failure=null;
        JsonElement? before=null,quote=null,receipt=null,after=null,serverAfter=null;
        try
        {
            before=await pipe.CallAsync(new{op="station.services.inventory"},stop.Token);quote=await Prices();
            var repair=quote.Value.GetProperty("servicePrices").GetProperty("repair");var costs=action=="integrity"?repair.GetProperty("shipIntegrityCosts"):repair;var cost=costs.GetProperty("costToRepair").GetInt64();
            if(cost is <=0 or >5000)throw new InvalidOperationException("Expected a nonzero bounded original repair quote.");
            if(journal.State.LoadGameAt!=initial.LoadGameAt||journal.State.CurrentShipId!=initial.CurrentShipId||!journal.State.Docked||journal.State.MarketId!=market)throw new InvalidOperationException("Docking or session changed.");
            await File.WriteAllTextAsync(path+".submitted.json",JsonSerializer.Serialize(new{key,market,pid,started,action,before,cost,instruction="Never resend an uncertain original service operation."},ToolboxSettings.JsonOptions));
            receipt=await Wait(await pipe.CallAsync(new{op="station.services",marketId=(uint)market,maintenanceAddress=address,action,operationKey=key},stop.Token));
            if(receipt.Value.GetProperty("state").GetInt32()!=3||!receipt.Value.GetProperty("serverConfirmed").GetBoolean()||!receipt.Value.GetProperty("clientApplied").GetBoolean())throw new InvalidOperationException("Original repair reply unconfirmed; reconcile before any further mutation.");
            after=await pipe.CallAsync(new{op="station.services.inventory"},stop.Token);
            if(after.Value.GetProperty("credits").GetInt64()!=before.Value.GetProperty("credits").GetInt64()-cost||after.Value.GetProperty("cargoCount").GetInt32()!=before.Value.GetProperty("cargoCount").GetInt32())throw new InvalidOperationException("Actual native wallet or cargo disagrees with repair receipt.");
            serverAfter=await Prices();var nextRepair=serverAfter.Value.GetProperty("servicePrices").GetProperty("repair");var next=action=="integrity"?nextRepair.GetProperty("shipIntegrityCosts"):nextRepair;
            if(next.GetProperty("costToRepair").GetInt64()!=0||action=="integrity"&&next.GetProperty("wear").GetInt32()!=0)throw new InvalidOperationException("A second original server quote did not confirm the repair.");
        }
        catch(Exception error){failure=error.ToString();}
        var passed=failure is null;await File.WriteAllTextAsync(path,JsonSerializer.Serialize(new{pid,market,started,finished=DateTimeOffset.UtcNow,key,action,passed,before,quote,receipt,after,serverAfter,failure,screenUse=false,osInputsSent=0,journalEventsSynthesized=0},ToolboxSettings.JsonOptions));
        Console.WriteLine(JsonSerializer.Serialize(new{passed,market,action,failure}));if(!passed)throw new InvalidOperationException("Native repair acceptance did not pass.");
    }
}