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

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
#if PLUGIN_SESSION_RECOVERY || PLUGIN_CRUISE_OBSERVATION || PLUGIN_CRUISE_CONTROL
using System.Text;
namespace XFEEDToolBox.Plugin;

internal static unsafe partial class Navigation
{
    internal sealed class RecoveryResetBinding
    {
        internal Snapshot baseline;
        internal JsonElement target;
        internal nuint node,source,registry,computer,events;
        internal float before,sourceBefore;
    }
    internal static void ConfigureRecoveryReadOnlyImage(){image=Platform.ImageBase;imageEnd=Platform.ImageEnd;}
    private static Snapshot RecoveryPlayer(ulong expectedEntity)
    {
        var pool=image+FsdPool;
        if(expectedEntity==0||Read<ulong>(pool+0x68)!=0xEC0||Read<ulong>(pool+0x90)>128)throw new InvalidOperationException("Reset player pool differs");
        var visited=new HashSet<nuint>();var block=Pointer(pool+0x30);Snapshot result=default;var found=0;
        while(block!=0&&visited.Add(block)&&visited.Count<=128)
        {
            var count=Read<ulong>(block+0x38);if(count is 0 or >128)throw new InvalidOperationException("Reset player pool bound");
            for(nuint i=0;i<(nuint)count;i++)
            {
                var fsd=block+0x80+i*0xEC0;
                if(Pointer(fsd)!=image+0x5316CC8||Pointer(fsd+0x58)!=image+0x5316DF8)continue;
                var owner=Pointer(fsd+0x20);var table=Pointer(owner);if(!InImage(table))continue;
                var reference=Leaf(owner,Pointer(table+0x20));if(reference==0)continue;var life=Pointer(reference);
                if(Read<uint>(life+0xC0)!=8||Read<ulong>(life+0xB0)!=expectedEntity)continue;
                if(++found!=1)throw new InvalidOperationException("Reset player is ambiguous");
                var physics=Pointer(fsd+0x2A8)-0x58;var input=Pointer(physics+0x3B0)-0x60;
                result=new(){entity=expectedEntity,life=life,fsd=fsd,physics=physics,inputRoot=input};
                if(!BoundFsd(result,fsd))throw new InvalidOperationException("Reset controlled actor changed");
            }
            block=Pointer(block+0x20);
        }
        if(block!=0||found!=1)throw new InvalidOperationException("Reset player is unavailable");return result;
    }
    internal static RecoveryResetBinding BindRecoveryReset(ulong entity,ulong world,JsonElement target,double hull,double? shield,nuint node)
    {
        var frame=RecoveryPlayer(entity);frame.referenceWorld=world;frame.healthValid=true;frame.hullFraction=hull;
        frame.shieldKnown=shield is not null;frame.shieldFraction=shield??0;
        var computer=LocalDockingComputer(frame);
        if(computer==0||Pointer(node)!=image+0x512E330||Pointer(node+0x40)!=Pointer(computer+0x230)
            ||Pointer(node+0x78)!=Pointer(computer+0x260)||Pointer(frame.fsd+0x6F8)!=Pointer(computer+0x230))throw new InvalidOperationException("Reset node does not belong to current main ship");
        return new(){baseline=frame,target=target.Clone(),node=node,source=Pointer(node+0x78),registry=Pointer(node+0x40),computer=computer,events=Pointer(node+0x68)};
    }
    private static bool RecoverySubscriber(RecoveryResetBinding proof)
    {
        var events=proof.events;var node=proof.node;
        if(events<0x10000||Pointer(node+0x68)!=events||Pointer(events)!=image+0x512EC98||Pointer(Pointer(events)+0x18)!=image+0x90C170
            ||Pointer(node+0x20)!=image+0x512E3A0||Pointer(Pointer(node+0x20))!=image+0x8F5320)return false;
        var set=events+0x9E0;var buckets=Pointer(set);var capacity=Read<ulong>(set+8);var used=Read<ulong>(set+0x18);
        if(buckets<0x10000||capacity is 0 or >8192||used is 0 or >4096)return false;
        var seen=new HashSet<nuint>();var matches=0;
        for(nuint i=0;i<(nuint)capacity;i++)
        {
            var head=buckets+i*8;var item=Pointer(head);
            while(item!=head)
            {
                if(item<0x10000||!seen.Add(item)||seen.Count>4096)return false;
                if(Pointer(item+8)==node+0x20)matches++;item=Pointer(item);
            }
        }
        return matches==1&&(ulong)seen.Count==used&&Pointer(set)==buckets&&Read<ulong>(set+8)==capacity&&Read<ulong>(set+0x18)==used;
    }
    private static bool RecoveryResetHealthEligible(Snapshot previous,Snapshot current)
        =>previous.healthValid&&current.healthValid&&previous.entity==current.entity&&previous.life==current.life
            &&double.IsFinite(current.hullFraction)&&current.hullFraction is >0 and <=1
            &&!HealthDamageEmergency(previous,current);
    private static Snapshot ReadRecoveryResetFrame(RecoveryResetBinding proof,nuint node)
    {
        if(node!=proof.node)throw new InvalidOperationException("Reset mapper identity differs");
        var current=RecoveryPlayer(proof.baseline.entity);
        if(current.life!=proof.baseline.life||current.fsd!=proof.baseline.fsd||current.physics!=proof.baseline.physics||current.inputRoot!=proof.baseline.inputRoot
            ||!Sample(current.physics,out var frame)||frame.entity!=proof.baseline.entity||frame.life!=current.life||frame.fsd!=current.fsd||frame.inputRoot!=current.inputRoot
            ||frame.referenceWorld!=proof.baseline.referenceWorld||!RecoveryResetHealthEligible(proof.baseline,frame)
            ||frame.rawFsdState is not(1 or 2)||!BoundFsd(frame,frame.fsd))throw new InvalidOperationException("Reset actual main ship or health changed");
        if(!SampleLocalFlight(frame,out var local,out var stage))throw new InvalidOperationException("Reset original flight telemetry unavailable: "+stage);
        var target=proof.target;
        if(local.target.key!=target.GetProperty("key").GetInt32()||local.target.body.ToString()!=target.GetProperty("bodyAddress").GetString()
            ||local.target.kind!=target.GetProperty("kind").GetUInt32()||local.target.market!=target.GetProperty("marketId").GetUInt32()
            ||LocalIdentityName(local.target)!=target.GetProperty("name").GetString()||!local.selected||local.inSupercruise||local.distance>7500
            ||!local.dockingVerified||!local.dockingGranted||local.nativeDockingActive||local.nativeLaunchActive||local.cruiseAssistEngaged)
            throw new InvalidOperationException("Reset actual target, ATC or native duty changed");
        var computer=LocalDockingComputer(frame);var dock=LocalDocking(frame);var controller=Pointer(frame.inputRoot+0x2F8);
        if(computer!=proof.computer||!LocalDockingAvailable(computer)||Pointer(computer+0x240)!=controller||Pointer(node+0x40)!=Pointer(computer+0x230)
            ||Pointer(node+0x40)!=Pointer(frame.fsd+0x6F8)||Pointer(node+0x78)!=proof.source||Pointer(computer+0x260)!=proof.source
            ||!FixtureBindingName(Pointer(node+0xB0),"ForwardReverseThrust_Set")||!FixtureBindingName(Pointer(node+0xB8),"SetSpeedZero")
            ||!FixtureBindingName(Pointer(node+0x90),"Bindings_Flight_Active")||dock==0||Read<uint>(dock+0x614)!=2||Read<uint>(dock+0x4C0)is not(3 or 4)||Read<byte>(dock+0x4E9)==255)
            throw new InvalidOperationException("Reset original input ownership or ATC differs");
        var registry=Pointer(node+0x40);
        if(Pointer(registry)!=image+0x512FD90||Pointer(Pointer(registry)+0x40)!=image+0x8FEDC0
            ||Pointer(Pointer(node+0xB0)+0x10)!=registry+0xB8||Pointer(Pointer(node+0xB8)+0x10)!=registry+0xB8||Pointer(proof.source+0x10)!=registry+0xB8)
            throw new InvalidOperationException("Reset exact registry aliases differ");
        var station=Pointer(dock+0x4E0);
        if(station==0||Read<uint>(station+0xC0)!=8||Read<ulong>(station+0xB0)!=local.target.market||!RecoverySubscriber(proof)
            ||!Platform.ReadBytes(image+0x8F5320,18).AsSpan().SequenceEqual(new byte[]{0xC6,0x81,0xC0,0,0,0,0,0xC7,0x81,0xB0,0,0,0,0,0,0,0,0xC3}))
            throw new InvalidOperationException("Reset original callback or subscription differs");
        return frame;
    }
    internal static void CallRecoveryReset(RecoveryResetBinding proof,nuint node,ulong deadline,Func<bool> stillAuthorized)
    {
        var frame=ReadRecoveryResetFrame(proof,node);var controller=Pointer(frame.inputRoot+0x2F8);
        proof.before=Read<float>(node+0xD0);
        proof.sourceBefore=Read<float>(proof.source+0x18);
        var actualBefore=Read<float>(frame.inputRoot+0x70);var controllerBefore=Read<float>(controller+0x680);var checkedAt=UtcMilliseconds();
        if(!float.IsFinite(proof.before)||Math.Abs(proof.before)>1.001f||!float.IsFinite(proof.sourceBefore)||Math.Abs(proof.sourceBefore)>1.001f||UtcMilliseconds()>=deadline||!stillAuthorized()
            ||!float.IsFinite(controllerBefore)||Math.Abs(controllerBefore)>.001f||!float.IsFinite(actualBefore)||Math.Abs(actualBefore)>.001f)
            throw new InvalidOperationException($"Reset pre-call refused: accumulator={proof.before:R}, source={proof.sourceBefore:R}, actual={actualBefore:R}, controller={controllerBefore:R}, observedAt={checkedAt}, originalDeadline={deadline}");
        // This original registered callback alone clears its own accumulator.
        // The following original mapper invocation computes the real output.
        Call(image+0x8F5320,(ulong)(node+0x20));
    }
}
#endif