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

XFEEDToolBox

【WinUI】XFE精英危险工具箱

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

namespace XFEEDToolBox.Core.Navigation;

public sealed record NativeTargetSelectionReadiness(bool CanRequest,bool Reject,string Reason,JsonElement Diagnostics);

/// <summary>Read-only arrival-tail qualification; the native selector remains authoritative.</summary>
public static class NativeTargetSelectionRecovery
{
    public static readonly TimeSpan MaximumWait=TimeSpan.FromSeconds(10);
    private static bool Flag(JsonElement value,string key,out bool output)
    {output=false;if(value.ValueKind!=JsonValueKind.Object||!value.TryGetProperty(key,out var field)||field.ValueKind is not(JsonValueKind.True or JsonValueKind.False))return false;output=field.GetBoolean();return true;}
    private static bool True(JsonElement value,string key)=>Flag(value,key,out var result)&&result;
    private static bool False(JsonElement value,string key)=>Flag(value,key,out var result)&&!result;
    private static long Integer(JsonElement value,string key)=>value.ValueKind==JsonValueKind.Object&&value.TryGetProperty(key,out var field)&&field.ValueKind==JsonValueKind.Number&&field.TryGetInt64(out var number)?number:-1;
    private static ulong Address(JsonElement value,string key)=>value.ValueKind==JsonValueKind.Object&&value.TryGetProperty(key,out var field)
        &&field.ValueKind==JsonValueKind.String&&ulong.TryParse(field.GetString(),NumberStyles.None,CultureInfo.InvariantCulture,out var number)?number:0;
    public static string? ContextFailure(PlayerState initial,PlayerState current,long target,DateTimeOffset now,TimeSpan elapsed)
    {
        if(elapsed<TimeSpan.Zero||elapsed>=MaximumWait)return "arrival-target-selection-deadline";
        if(!initial.InGame||initial.CommanderId.Length==0||initial.CurrentShipId is not >=0||initial.LoadGameAt is null||initial.Navigation.CurrentSystemAddress is not >0
            ||initial.Navigation.LastJumpAt is not {} arrived||arrived<initial.LoadGameAt.Value||initial.Navigation.CurrentSystemAt!=arrived||initial.Navigation.JumpInProgress
            ||!GameJournalClock.IsRecentArrival(initial,now))return "arrival-identity-or-window-unverified";
        if(!current.InGame||current.Docked||current.CommanderId!=initial.CommanderId||current.CurrentShipId!=initial.CurrentShipId
            ||current.LoadGameAt!=initial.LoadGameAt||current.GameMode!=initial.GameMode||current.CargoCount!=initial.CargoCount
            ||current.Navigation.CurrentSystemAddress!=initial.Navigation.CurrentSystemAddress||current.Navigation.LastJumpAt!=initial.Navigation.LastJumpAt
            ||current.Navigation.CurrentSystemAt!=initial.Navigation.CurrentSystemAt||current.Navigation.JumpInProgress
            ||!GameJournalClock.IsRecentArrival(current,now))return "arrival-flight-identity-changed";
        if(NavigationSafety.UnhealthyHull(current))return "arrival-ship-health-failed";
        if(NavigationSafety.HasExternalThreat(current))return "arrival-external-threat";
        var planned=initial.Navigation.Route.Select(point=>point.SystemAddress).ToArray();
        if(target<=0||!planned.Contains(target)||!NavigationRouteProgress.SameItinerary(planned,current.Navigation)
            ||current.Navigation.TargetSystemAddress is >0 and var selected&&selected!=target)return "arrival-route-or-selected-target-changed";
        return null;
    }
    public static NativeTargetSelectionReadiness Inspect(JsonElement raw,JsonElement fsd,long target,long expectedSystem,DateTimeOffset now)
    {
        var entity=Address(raw,"entityId");var fsdEntity=Address(fsd,"entityId");var at=Integer(raw,"observedAtUnixMilliseconds");
        var rawState=Integer(raw,"rawFsdState");var state=Integer(fsd,"state");
        var health=raw.ValueKind==JsonValueKind.Object&&raw.TryGetProperty("shipHealth",out var h)?h:default;
        var hull=health.ValueKind==JsonValueKind.Object&&health.TryGetProperty("hullFraction",out var hullNode)&&hullNode.ValueKind==JsonValueKind.Number?hullNode.GetDouble():double.NaN;
        var sequence=Integer(raw,"sequence");var healthSequence=Integer(health,"sequence");var healthAt=Integer(health,"observedAtUnixMilliseconds");
        var stamp=now.ToUnixTimeMilliseconds();var age=at>0?stamp-at:long.MaxValue;
        var world=Address(raw,"referenceWorldAddress");
        var identity=True(raw,"localPlayerShipVerified")&&entity!=0&&entity==fsdEntity&&entity==Address(health,"entityId")
            &&world!=0&&expectedSystem>0&&NativeFrameProjector.SystemAddressFromBody(world)==expectedSystem;
        var healthVerified=True(health,"verified")&&sequence>0&&healthSequence==sequence&&healthAt==at&&double.IsFinite(hull)&&hull is >0 and <=1&&False(health,"emergency")&&False(health,"damageObserved");
        var fresh=age is >=-100 and <=300&&True(fsd,"fresh");
        var locked=True(fsd,"targetValid")&&Address(fsd,"targetAddress")==unchecked((ulong)target);
        var nativeIdle=rawState==2&&state==2;
        var matchingExisting=locked&&(rawState is 0 or 1 or 2 or 5)&&(state is 0 or 1 or 2 or 5);
        var negativeSafety=True(raw,"playerOverride")||True(health,"emergency")||True(health,"damageObserved")||double.IsFinite(hull)&&hull<=0;
        var rejected=negativeSafety||False(raw,"inGame");
        var canRequest=!rejected&&target>0&&fresh&&identity&&healthVerified&&True(raw,"inGame")&&False(raw,"playerOverride")
            &&False(fsd,"ownedCharging")&&(nativeIdle||matchingExisting);
        var reason=negativeSafety?"native-manual-or-health-rejection":False(raw,"inGame")?"native-session-ended":canRequest?"native-idle-or-exact-existing-target-qualified"
            :!fresh?"awaiting-fresh-arrival-snapshots":!identity?"awaiting-same-main-ship-identity":!healthVerified?"awaiting-verified-healthy-arrival"
            :!False(fsd,"ownedCharging")||rawState is 3 or 4||state is 3 or 4?"awaiting-original-fsd-transition-without-input":"awaiting-native-target-selection-eligibility";
        var diagnostics=JsonSerializer.SerializeToElement(new{reason,targetSystemAddress=target,entityId=entity.ToString(CultureInfo.InvariantCulture),fsdEntityId=fsdEntity.ToString(CultureInfo.InvariantCulture),
            referenceWorldAddress=world.ToString(CultureInfo.InvariantCulture),expectedSystemAddress=expectedSystem,observedAtUnixMilliseconds=at,ageMilliseconds=at>0?(long?)age:null,rawState,fsdState=state,fsdFresh=True(fsd,"fresh"),ownedCharging=Flag(fsd,"ownedCharging",out var owned)?(bool?)owned:null,
            targetValid=True(fsd,"targetValid"),targetAddress=Address(fsd,"targetAddress").ToString(CultureInfo.InvariantCulture),rawInGame=Flag(raw,"inGame",out var inGame)?(bool?)inGame:null,
            playerOverride=Flag(raw,"playerOverride",out var manual)?(bool?)manual:null,identityVerified=identity,healthVerified,hullFraction=double.IsFinite(hull)?(double?)hull:null,
            sequence,healthSequence,healthObservedAtUnixMilliseconds=healthAt,
            emergency=Flag(health,"emergency",out var emergency)?(bool?)emergency:null,damageObserved=Flag(health,"damageObserved",out var damage)?(bool?)damage:null,
            nativeReady=canRequest,mutationsSent=0});
        return new(canRequest,rejected,reason,diagnostics);
    }
}