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

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Text;
using System.Text.Json;
using System.Text.Json.Nodes;
using static XFEEDToolBox.Plugin.JsonWire;
namespace XFEEDToolBox.Plugin;
internal static unsafe partial class Navigation
{
    // One-use, fixed-value empty-ship diagnostic, not a general throttle API.
    // Only the original node may write its accumulator and computed output.
    private struct DockingFixture
    {
        public string? id,issue;
        public LocalActionRequest command;
        public uint stage,unseededFrames;
        public nuint node,binding,source;
        public ulong until,seedSequence,lastSequence,utc;
        public float before,accumulator,sourceValue,commandValue;
        public bool restored,zeroVerified;
    }
    private struct DockingFixturePulse
    {
        public nuint node,binding,source;
        public float beforeAccumulator;
        public bool applied;
    }
    private static DockingFixture dockingFixture;
    private static readonly HashSet<string> dockingFixtureUsed=new(StringComparer.Ordinal);
    private static bool FixtureGeometryEligible(double distance,double speed,double outwardCosine)
        =>double.IsFinite(distance)&&distance is >=4500 and <=7200&&double.IsFinite(speed)&&speed is >=0 and <=15&&double.IsFinite(outwardCosine)&&outwardCosine>=.98;
    private static void ExpireDockingFixture(){lock(localLock){dockingFixture.command.expires=0;dockingFixture.until=0;}}
    private static JsonObject DockingFixtureRequest(string op,JsonElement request,string owner,in Snapshot frame)
    {
        var now=GetTickCount64();var id=request.Str("trialId");
        if(id.Length!=32||id.Any(c=>!"0123456789abcdef".Contains(c)))throw new InvalidOperationException("Explicit one-use docking trial identity required");
        LocalSelection selection;lock(localLock)selection=localSelection;
        if(clientOwner!=owner||request.U64("generation")!=selection.generation||localConfirmed!=selection.generation)throw new InvalidOperationException("Docking trial must belong to the current selected controller");
        lock(localLock)
        {
            if(op=="docking.validation.arm")
            {
                if(dockingFixture.id==id)return DockingFixtureDescription(now);
                if(dockingFixtureUsed.Contains(id)||dockingFixtureUsed.Count>=32||dockingFixture.until>now)throw new InvalidOperationException("Docking trial consumed or another trial active");
                if(!dockingInputMapperReady||!Enabled()||!inGame||!frame.valid||!frame.healthValid||frame.healthEmergency||frame.hullFraction<.95||overridden||frame.rawFsdState is not(1 or 2)||fsdOwned||selection.entity!=frame.entity||selection.life!=frame.life)throw new InvalidOperationException("Fresh healthy normal-space main ship required for empty docking trial");
                var reference=Reference(request.U64("sequence"),frame,now);dockingFixtureUsed.Add(id);
                dockingFixtureDiagnostics=default;
                dockingFixture=new(){id=id,stage=1,until=now+15000,command=new(){expires=Math.Min(now+250,reference.tick+300),sequence=reference.sequence,selection=selection.generation,entity=frame.entity,life=frame.life,inputRoot=frame.inputRoot,world=frame.referenceWorld,epoch=controllerEpoch}};
            }
            else
            {
                if(dockingFixture.id!=id)throw new InvalidOperationException("No matching docking diagnostic trial");
                if(op=="docking.validation.cancel"){dockingFixture.command.expires=0;dockingFixture.until=0;}
            }
            return DockingFixtureDescription(now);
        }
    }
    private static JsonObject DockingFixtureDescription(ulong now)
    {
        if(dockingFixture.stage==1&&dockingFixture.command.expires<=now){dockingFixture.stage=6;dockingFixture.issue??="Eligible original mapper did not consume the diagnostic before its deadline";}
        return Obj(("trialId",dockingFixture.id),("stage",dockingFixture.stage),("issue",dockingFixture.issue),("oneUse",true),("fixedCommand",.75),("seedSequence",dockingFixture.seedSequence),("lastSequence",dockingFixture.lastSequence),("unseededFrames",dockingFixture.unseededFrames),("observedAtUnixMilliseconds",dockingFixture.utc),("accumulatorBefore",dockingFixture.before),("accumulatorAfter",dockingFixture.accumulator),("sourceAfter",dockingFixture.sourceValue),("commandAfter",dockingFixture.commandValue),("commandRestored",dockingFixture.restored),("zeroVerified",dockingFixture.zeroVerified),("persistent075",dockingFixture.unseededFrames>=3),("gameAccumulatorWrittenBySdk",false),("gameOutputWrittenBySdk",false),("diagnostics",DockingFixtureDiagnosticsDescription()));
    }
    private static nuint ResolveFixtureBinding(nuint actions,nuint name)
    {
        var scratch=stackalloc byte[47];var temporary=AlignServiceScratch(scratch);new Span<byte>(temporary,32).Clear();
        try{Call(image+0x8FEDC0,actions,(ulong)(nuint)temporary,name);return Pointer((nuint)temporary);}
        finally{Call(image+0x204010,(ulong)(nuint)temporary);}
    }
    private static bool FixtureBindingName(nuint binding,string expected)
    {
        if(binding<0x10000||Read<int>(binding)<=0)return false;
        var text=Pointer(binding+8);if(text<0x10000||Read<ulong>(text)!=(ulong)expected.Length)return false;
        return Platform.ReadBytes(text+0x14,expected.Length).AsSpan().SequenceEqual(Encoding.ASCII.GetBytes(expected));
    }
    private static bool BeginDockingFixturePulse(nuint node,nuint binding,nuint source,out DockingFixturePulse pulse)
    {
        pulse=default;if(node<0x10000||binding<0x10000||source<0x10000||binding==source||Pointer(node+0xB0)!=binding||Pointer(node+0x78)!=source||Read<int>(binding)<=0||Read<uint>(binding+0x18)!=0)return false;
        var before=Read<float>(node+0xD0);if(!float.IsFinite(before)||Math.Abs(before)>1.001f)return false;
        pulse=new(){node=node,binding=binding,source=source,beforeAccumulator=before,applied=true};Write(binding+0x18,.75f);return true;
    }
    private static void EndDockingFixturePulse(in DockingFixturePulse pulse)
    {
        if(pulse.applied&&Pointer(pulse.node+0xB0)==pulse.binding&&Pointer(pulse.node+0x78)==pulse.source&&Read<uint>(pulse.binding+0x18)==0x3F400000)Write(pulse.binding+0x18,0u);
    }
    private static bool PrepareDockingFixturePulse(nuint node,float dt,out DockingFixturePulse pulse)
    {
        pulse=default;DockingFixture wanted;LocalSelection selection;LocalFlightObservation observed;
        lock(localLock){wanted=dockingFixture;selection=localSelection;observed=localObservation;}
        var now=GetTickCount64();if(wanted.stage!=1||wanted.command.expires<=now)return false;
        BeginFixtureDiagnostics(node,dt,now);
        if(!dockingInputMapperReady)return RefuseFixture(FixtureRefusal.MapperReady);
        if(GetCurrentThreadId()!=owningThread)return RefuseFixture(FixtureRefusal.Thread);
        if(!float.IsFinite(dt)||dt<=0||dt>.25f)return RefuseFixture(FixtureRefusal.DeltaTime);
        var frame=Current();var command=wanted.command;
        lock(localLock){dockingFixtureDiagnostics.frameAge=now>=frame.tick?now-frame.tick:ulong.MaxValue;dockingFixtureDiagnostics.observationAge=now>=observed.tick?now-observed.tick:ulong.MaxValue;}
        if(!Enabled())return RefuseFixture(FixtureRefusal.Enabled);
        if(!inGame)return RefuseFixture(FixtureRefusal.InGame);
        if(!frame.valid)return RefuseFixture(FixtureRefusal.FrameValid);
        if(!frame.healthValid||frame.healthEmergency||frame.hullFraction<.95)return RefuseFixture(FixtureRefusal.Health);
        if(overridden)return RefuseFixture(FixtureRefusal.Override);
        if(fsdOwned)return RefuseFixture(FixtureRefusal.FsdOwned);
        if(frame.rawFsdState is not(1 or 2))return RefuseFixture(FixtureRefusal.FsdState);
        if(now<frame.tick||now-frame.tick>200)return RefuseFixture(FixtureRefusal.FrameFresh);
        if(command.entity!=frame.entity)return RefuseFixture(FixtureRefusal.Entity);
        if(command.life!=frame.life)return RefuseFixture(FixtureRefusal.Life);
        if(command.inputRoot!=frame.inputRoot)return RefuseFixture(FixtureRefusal.InputRoot);
        if(command.world!=frame.referenceWorld)return RefuseFixture(FixtureRefusal.World);
        if(command.epoch!=controllerEpoch)return RefuseFixture(FixtureRefusal.Epoch);
        if(command.selection!=selection.generation)return RefuseFixture(FixtureRefusal.Selection);
        if(localConfirmed!=selection.generation)return RefuseFixture(FixtureRefusal.Confirmation);
        if(!BoundFsd(frame,frame.fsd))return RefuseFixture(FixtureRefusal.FsdBinding);
        if(!observed.valid)return RefuseFixture(FixtureRefusal.ObservationValid);
        if(observed.entity!=frame.entity)return RefuseFixture(FixtureRefusal.ObservationEntity);
        if(now<observed.tick||now-observed.tick>200)return RefuseFixture(FixtureRefusal.ObservationFresh);
        if(observed.inSupercruise)return RefuseFixture(FixtureRefusal.Supercruise);
        if(!SameLocal(observed.target,selection.target))return RefuseFixture(FixtureRefusal.Target);
        if(observed.nativeDockingActive)return RefuseFixture(FixtureRefusal.DockingDuty);
        if(observed.nativeLaunchActive)return RefuseFixture(FixtureRefusal.LaunchDuty);
        if(observed.nativeLaunchRequested)return RefuseFixture(FixtureRefusal.LaunchRequest);
        if(observed.cruiseAssistEnabled)return RefuseFixture(FixtureRefusal.ScaEnabled);
        if(observed.cruiseAssistEngaged)return RefuseFixture(FixtureRefusal.ScaEngaged);
        var outward=Subtract(observed.ship.position,observed.destination.position);var length=Math.Sqrt(Dot(outward,outward));
        if(length<=0||!FixtureGeometryEligible(observed.distance,observed.speed,Dot(outward,observed.ship.forward)/length))return RefuseFixture(FixtureRefusal.Geometry);
        bool released;ulong flightUntil,fsdUntil;lock(leaseLock){flightUntil=lease.expires;fsdUntil=fsdLease.expires;released=flightUntil<=now&&fsdUntil<=now;}
        lock(localLock){dockingFixtureDiagnostics.leaseUntil=flightUntil;dockingFixtureDiagnostics.fsdLeaseUntil=fsdUntil;}
        if(!released)return RefuseFixture(FixtureRefusal.Lease);
        var inventory=ReadCommerceShipInventory(frame);
        lock(localLock){dockingFixtureDiagnostics.inventoryVerified=inventory.verified;dockingFixtureDiagnostics.cargoCount=inventory.count;dockingFixtureDiagnostics.cargoCapacity=inventory.capacity;}
        if(!inventory.verified||inventory.count!=0||inventory.capacity!=192)return RefuseFixture(FixtureRefusal.Inventory);
        var computer=LocalDockingComputer(frame);if(computer==0||!LocalDockingAvailable(computer))return RefuseFixture(FixtureRefusal.Computer);
        var source=Pointer(computer+0x260);lock(localLock)dockingFixtureDiagnostics.source=source;
        if(source==0||Pointer(node+0x78)!=source)return RefuseFixture(FixtureRefusal.SourceAlias);
        var actions=Pointer(computer+0x230);var active=Pointer(node+0x90);
        lock(localLock){dockingFixtureDiagnostics.registry=Pointer(node+0x40);dockingFixtureDiagnostics.active=active;dockingFixtureDiagnostics.activeFlag=active>=0x10000?Read<byte>(active+0x24):(byte)0;}
        if(actions==0||Pointer(actions)!=image+0x512FD90||Pointer(Pointer(actions)+0x40)!=image+0x8FEDC0||Pointer(node+0x40)!=actions)return RefuseFixture(FixtureRefusal.Registry);
        if(active<0x10000||Read<byte>(active+0x24)==0)return RefuseFixture(FixtureRefusal.ActiveBinding);
        if((byte)Call(image+0xED6620,computer)!=0)return RefuseFixture(FixtureRefusal.AiDuty);
        var dock=LocalDocking(frame);if(dock==0||Read<uint>(dock+0x4C0)is 5 or 7)return RefuseFixture(FixtureRefusal.DockState);
        if(Read<uint>(dock+0x614)==2)return RefuseFixture(FixtureRefusal.RequestState);
        var absolute=ResolveFixtureBinding(actions,image+0x532FD58);var zero=ResolveFixtureBinding(actions,image+0x531A568);
        lock(localLock){dockingFixtureDiagnostics.absolute=Pointer(node+0xB0);dockingFixtureDiagnostics.zero=Pointer(node+0xB8);var a=Read<float>(node+0xD0);var b=Read<float>(absolute+0x18);dockingFixtureDiagnostics.accumulator=float.IsFinite(a)?a:0;dockingFixtureDiagnostics.absoluteValue=float.IsFinite(b)?b:0;}
        if(!FixtureBindingName(absolute,"ForwardReverseThrust_Set"))return RefuseFixture(FixtureRefusal.AbsoluteName);
        if(!FixtureBindingName(zero,"SetSpeedZero"))return RefuseFixture(FixtureRefusal.ZeroName);
        if(Pointer(node+0xB0)!=absolute)return RefuseFixture(FixtureRefusal.AbsoluteAlias);
        if(!DockingMapperNodeMatches(node,zero,source))return RefuseFixture(FixtureRefusal.ZeroAlias);
        if(Read<byte>(zero+0x24)!=0)return RefuseFixture(FixtureRefusal.ZeroAlreadySet);
        if(!BeginDockingFixturePulse(node,absolute,source,out pulse))return RefuseFixture(FixtureRefusal.Pulse);
        lock(localLock){dockingFixture.node=node;dockingFixture.binding=absolute;dockingFixture.source=source;}return true;
    }
    private static void ObserveDockingFixtureMapper(nuint node,in DockingFixturePulse pulse,in DockingMapperPulse zeroPulse)
    {
        DockingFixture wanted;lock(localLock)wanted=dockingFixture;
        if(wanted.node!=node||wanted.until<=GetTickCount64()||wanted.stage is not(1 or 2 or 3)||Pointer(node+0xB0)!=wanted.binding||Pointer(node+0x78)!=wanted.source)return;
        var frame=Current();if(frame.entity!=wanted.command.entity||frame.life!=wanted.command.life)return;
        var accumulator=Read<float>(node+0xD0);var source=Read<float>(wanted.source+0x18);var command=Read<float>(wanted.binding+0x18);var finite=float.IsFinite(accumulator)&&float.IsFinite(source)&&float.IsFinite(command);
        lock(localLock)
        {
            dockingFixture.utc=UtcMilliseconds();dockingFixture.accumulator=finite?accumulator:0;dockingFixture.sourceValue=finite?source:0;dockingFixture.commandValue=finite?command:0;
            if(pulse.applied)
            {
                dockingFixture.before=pulse.beforeAccumulator;dockingFixture.seedSequence=frame.sequence;dockingFixture.lastSequence=frame.sequence;dockingFixture.restored=command==0;
                dockingFixture.stage=finite&&Math.Abs(accumulator-.75f)<.001f&&Math.Abs(source-.75f)<.001f&&command==0?2u:6u;
                if(dockingFixture.stage==6)dockingFixture.issue="Original absolute command did not produce retained .75 state";
            }
            else if(zeroPulse.applied&&wanted.unseededFrames>=3&&Math.Abs(zeroPulse.beforeAccumulator-.75f)<.001f&&finite&&Math.Abs(accumulator)<.001f&&Math.Abs(source)<.001f)
            {dockingFixture.zeroVerified=true;dockingFixture.stage=4;dockingFixture.lastSequence=frame.sequence;}
            else if(frame.sequence>wanted.lastSequence)
            {
                dockingFixture.lastSequence=frame.sequence;
                if(finite&&Math.Abs(accumulator-.75f)<.001f&&Math.Abs(source-.75f)<.001f&&command==0){dockingFixture.unseededFrames++;if(dockingFixture.unseededFrames>=3)dockingFixture.stage=3;}
                else{dockingFixture.stage=6;dockingFixture.issue="Unseeded original graph did not retain .75; not a valid reproduction";}
            }
        }
    }
}