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

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Text.Json;

namespace XFEEDToolBox.Core.Navigation;

/// <summary>A fresh original save transition is distinct from a pause or a missing flight sample.</summary>
public static class SavingSceneRecovery
{
    public static bool Matches(JsonElement frame,int processId,string gameHash,DateTimeOffset now)
    {
        try
        {
            return processId>0&&frame.GetProperty("available").ValueKind==JsonValueKind.True
                &&frame.GetProperty("processId").GetInt32()==processId&&frame.GetProperty("gameSha256").GetString()==gameHash
                &&frame.GetProperty("state").GetString()=="SaveGameOnEnterLocation"&&frame.GetProperty("nextState").GetString()=="InGame"
                &&now.ToUnixTimeMilliseconds()-frame.GetProperty("observedAtUnixMilliseconds").GetInt64() is >=0 and <=500;
        }
        catch(Exception error)when(error is KeyNotFoundException or InvalidOperationException or FormatException or OverflowException){return false;}
    }
    public static async Task<bool> ReadAsync(int processId,string gameHash,CancellationToken token)
    {
        try
        {
            // A fresh token has never acquired ownership. This returns only the
            // service description; it cannot end another owner's session.
            var frame=await new NavigationPipeClient(processId).CallAsync(new{op="session.end",owner=Guid.NewGuid().ToString("N")},token);
            return Matches(frame,processId,gameHash,DateTimeOffset.UtcNow);
        }
        catch(Exception error)when(!token.IsCancellationRequested&&error is IOException or InvalidOperationException or OperationCanceledException){return false;}
    }
}

public sealed class SavingSceneRecoveryRequiredException(Exception inner):InvalidOperationException("原版抵达位置保存尚未完成,需要核对场景后恢复原航程。",inner)
{
    public static bool Present(Exception error)=>error is SavingSceneRecoveryRequiredException||error.InnerException is {} inner&&Present(inner);
}