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

XFEEDToolBox

【WinUI】XFE精英危险工具箱

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

namespace XFEEDToolBox.Plugin;

internal static unsafe partial class Navigation
{
    internal sealed record GameRouteOptions(int? mode,bool? useJetConeBoost,int? fsdBoostLevel,float? virtualCargoMass,uint? starClassMask=null,GalaxyRouteMapFilterRequest? mapFilter=null);
    internal readonly record struct GameRouteOptionsSnapshot(int mode,bool jetCone,int boostLevel,float cargoMass,bool boostEnabled);

    static GameRouteOptions? ParseGameRouteOptions(JsonElement request)
    {
        if(!request.TryGetProperty("routeOptions",out var input)||input.ValueKind==JsonValueKind.Null)return null;
        if(input.ValueKind!=JsonValueKind.Object)throw new InvalidDataException("Invalid original route options");
        int? Integer(string name,int maximum)
        {
            if(!input.TryGetProperty(name,out var value)||value.ValueKind==JsonValueKind.Null)return null;
            if(value.ValueKind!=JsonValueKind.Number||!value.TryGetInt32(out var number)||number<0||number>maximum)
                throw new InvalidDataException("Invalid original route option: "+name);
            return number;
        }
        var mode=Integer("mode",2);var boost=Integer("fsdBoostLevel",3);var starMask=Integer("starClassMask",0xFFFF);bool? jet=null;float? cargo=null;
        if(input.TryGetProperty("useJetConeBoost",out var j)&&j.ValueKind!=JsonValueKind.Null)
        {if(j.ValueKind is not(JsonValueKind.True or JsonValueKind.False))throw new InvalidDataException("Invalid jet cone option");jet=j.GetBoolean();}
        if(input.TryGetProperty("virtualCargoMass",out var c)&&c.ValueKind!=JsonValueKind.Null)
        {if(c.ValueKind!=JsonValueKind.Number||!c.TryGetSingle(out var mass)||!float.IsFinite(mass)||mass is <0 or >2048)throw new InvalidDataException("Invalid route cargo mass");cargo=mass;}
        if(boost is not null&&mode!=2)throw new InvalidDataException("FSD boost level requires original boost mode");
        var mapFilter=ParseGalaxyRouteMapFilter(input);
        return mode is null&&boost is null&&jet is null&&cargo is null&&starMask is null&&mapFilter is null?null:new(mode,jet,boost,cargo,(uint?)starMask,mapFilter);
    }

    // Original Settings+1F0 ready branch: active profile stride248, uint array54.
    // No original getter, fallback, loader or setter is called by this reader.
    static bool CopyGameRouteJetCone(nuint settings,nuint expectedImage,out bool jet)
    {
        jet=false;
        try
        {
            if(settings<0x10000)return false;var table=Pointer(settings);
            if(table<0x10000||Pointer(table+0x1F0)!=expectedImage+0x2601B60||Pointer(table+0x200)!=expectedImage+0x2646760||Read<int>(settings+0x5F8)!=2)return false;
            var count=Read<uint>(settings+0x530);var index=Read<uint>(settings+0x560);var rows=Pointer(settings+0x538);
            if(count is <1 or >128||index>=count||rows<0x10000)return false;
            var at=rows+(nuint)index*0x248+0x54+29*4;var value=Read<uint>(at);
            if(value>1||Pointer(settings)!=table||Read<int>(settings+0x5F8)!=2||Read<uint>(settings+0x530)!=count||
                Read<uint>(settings+0x560)!=index||Pointer(settings+0x538)!=rows||Read<uint>(at)!=value)return false;
            jet=value!=0;return true;
        }
        catch{return false;}
    }
    static bool CopyGameRouteOptions(nuint component,nuint expectedImage,out nuint controller,out GameRouteOptionsSnapshot snapshot)
    {
        controller=0;snapshot=default;
        try
        {
            if(component<0x10058||Pointer(component)!=expectedImage+0x551FE98||
                Pointer(expectedImage+0x551FE98)!=expectedImage+0x3A4C030)return false;
            var main=component+0x30;var table=expectedImage+0x551FFC0;
            if(Pointer(main)!=table||Pointer(table+0xF0)!=expectedImage+0x3A6AEB0||Pointer(table+0xF8)!=expectedImage+0x3A6AFA0||
                Pointer(table+0x100)!=expectedImage+0x3A6AE10||Pointer(table+0x108)!=expectedImage+0x3A6AD80)return false;
            var settings=Pointer(main+0x1B8);if(!CopyGameRouteJetCone(settings,expectedImage,out var jet))return false;
            var mode=Read<int>(main+0x5AC);var cargo=Read<float>(main+0x5B0);var active=Read<byte>(main+0x5B4);var boost=Read<int>(main+0x5B8);
            if(mode is <0 or >2||!float.IsFinite(cargo)||cargo is <0 or >2048||active>1||boost is <0 or >3)return false;
            if(Pointer(component)!=expectedImage+0x551FE98||Pointer(main)!=table||Pointer(main+0x1B8)!=settings||
                Read<int>(main+0x5AC)!=mode||Read<float>(main+0x5B0)!=cargo||Read<byte>(main+0x5B4)!=active||Read<int>(main+0x5B8)!=boost)return false;
            controller=main;snapshot=new(mode,jet,boost,cargo,active!=0);return true;
        }
        catch{controller=0;snapshot=default;return false;}
    }
    static bool GameRouteOptionsAllowed(nuint main,nuint expectedImage,GameRouteOptions options)
    {
        // All four original setters reject view1; only the mode setter also
        // rejects view3. Preserve that distinction instead of blanket gating.
        if(Read<int>(main+0x220)!=-1)return true;
        var navigation=Pointer(main+0x228);if(navigation==0)return true;
        var view=CopyGalaxyNavRouteViewMode(navigation,expectedImage);
        return view is not null and not 1&&(options.mode is null||view!=3);
    }

    static bool ApplyGameRouteOptions(Snapshot frame,GameRouteOptions options)
    {
        if(!Enabled()||!inGame||GetCurrentThreadId()!=owningThread||!frame.valid||!FindGalaxyServices(frame,out var services))return false;
        var type=Read<uint>(image+0x5FDB224);var component=RegisteredComponent(services.registry,type);
        if(!CopyGameRouteOptions(component,image,out var main,out _)||!GameRouteOptionsAllowed(main,image,options))return false;
        if(options.starClassMask is not null&&!CopyGalaxyRouteStarClassState(main,image,out _))return false;
        if(options.mapFilter is{} map&&!CopyGalaxyRouteCheckboxState(main,image,map,out _))return false;
        bool CurrentController()=>Current() is{valid:true} currentFrame&&currentFrame.entity==frame.entity&&Read<uint>(image+0x5FDB224)==type&&
            RegisteredComponent(services.registry,type)==component&&CopyGameRouteOptions(component,image,out var current,out _)&&current==main&&GameRouteOptionsAllowed(current,image,options);
        // Invoke the four actual current UI setters on their owning thread,
        // with the recovered integer/bool/XMM1 ABIs. Never write game fields.
        if(options.virtualCargoMass is{} cargo)
        {if(!CurrentController())return false;((delegate* unmanaged<nuint,float,void>)(image+0x3A6AD80))(main,cargo);}
        if(options.fsdBoostLevel is{} level)
        {if(!CurrentController())return false;((delegate* unmanaged<nuint,float,void>)(image+0x3A6AE10))(main,level);}
        if(options.useJetConeBoost is{} jet)
        {if(!CurrentController())return false;((delegate* unmanaged<nuint,byte,void>)(image+0x3A6AFA0))(main,jet?(byte)1:(byte)0);}
        // Boost's setter enables its mode flag. Apply the explicit mode last,
        // just as the original radio selection does, then verify every override.
        if(options.mode is{} mode)
        {if(!CurrentController())return false;((delegate* unmanaged<nuint,int,void>)(image+0x3A6AEB0))(main,mode);}
        if(!CurrentController()||!CopyGameRouteOptions(component,image,out _,out var actual))return false;
        return (options.mode is null||actual.mode==options.mode)&&
            (options.virtualCargoMass is null||actual.cargoMass==options.virtualCargoMass)&&
            (options.useJetConeBoost is null||actual.jetCone==options.useJetConeBoost)&&
            (options.fsdBoostLevel is null||actual.boostLevel==options.fsdBoostLevel&&actual.boostEnabled)&&
            (options.starClassMask is not{} mask||ApplyGalaxyStarClassRouteFilter(frame,mask))&&
            (options.mapFilter is not{} mapFilter||ApplyGalaxyRouteMapFilter(frame,mapFilter));
    }
}