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

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
namespace XFEEDToolBox.Plugin;

internal static unsafe partial class Navigation
{
    internal readonly record struct GalaxyRouteStarClassState(nuint mapController,nuint provider,uint mask);
    static bool ValidGalaxyRouteStarMask(uint mask)=>(mask&~0xFFFFu)==0;

    // Same packed mask as original3B17970, copied without invoking its
    // iterator bookkeeping. Fifteen actual rows and the independent final
    // route checkbox are required; no future/missing row is guessed.
    static bool CopyGalaxyRouteStarClassState(nuint main,nuint expectedImage,out GalaxyRouteStarClassState result)
    {
        result=default;
        try
        {
            if(main<0x10000||Pointer(main)!=expectedImage+0x551FFC0||
               Pointer(expectedImage+0x551FFC0+0x78)!=expectedImage+0x3A68F60||Read<int>(main+0x280)!=-1)return false;
            var type=Pointer(main+0x288);if(type<0x10028||Pointer(type)!=expectedImage+0x552D788)return false;
            var controller=type-0x28;
            if(Pointer(controller)!=expectedImage+0x552D5C0||Pointer(expectedImage+0x552D5C0+0x40)!=expectedImage+0x3B45E30)return false;
            // Original3B16B00's case5 shared handle is at owner388/390;
            // controller is owner+58, so its members are330/338.
            var block=Pointer(controller+0x330);var provider=Pointer(controller+0x338);
            if(block<0x10000||Read<int>(block+8)<=0||Read<int>(block+0xC)<=0||provider<0x10000||
               Pointer(provider)!=expectedImage+0x552E100||Pointer(expectedImage+0x552E100+0x28)!=expectedImage+0x3B8BA80||
               Pointer(expectedImage+0x552E100+0x30)!=expectedImage+0x3B178D0||Read<int>(provider+0x60)!=5||Read<byte>(provider+0x80)!=1)return false;
            var count=Read<ulong>(provider+0x90);var capacity=Read<ulong>(provider+0x98);var storage=Pointer(provider+0xA0);
            var affects=Read<byte>(provider+0x81);
            if(count!=15||capacity is <16 or >256||(capacity&(capacity-1))!=0||storage<0x10000||affects>1)return false;
            var values=new List<(nuint at,uint index,byte selected)>();var bitmaps=new List<(nuint at,ulong bits)>();
            var rows=storage+(nuint)(((capacity>>3)+7)&~7UL);uint seen=0,mask=0;var occupied=0;
            for(ulong bucket=0;bucket<capacity;bucket++)
            {
                var at=storage+(nuint)(bucket>>6)*8;var bits=Read<ulong>(at);
                if((bucket&63)==0)bitmaps.Add((at,bits));
                if((bits&(1UL<<(int)(bucket&63)))==0)continue;
                var row=rows+(nuint)bucket*0x38;var index=Read<uint>(row+8);var selected=Read<byte>(row+0x30);
                if(index>=15||selected>1||(seen&(1u<<(int)index))!=0)return false;
                seen|=1u<<(int)index;if(selected!=0)mask|=1u<<(int)index;
                values.Add((row,index,selected));occupied++;
            }
            if(occupied!=15||seen!=0x7FFF||Pointer(main)!=expectedImage+0x551FFC0||Read<int>(main+0x280)!=-1||
               Pointer(main+0x288)!=type||Pointer(type)!=expectedImage+0x552D788||Pointer(controller)!=expectedImage+0x552D5C0||
               Pointer(controller+0x330)!=block||Pointer(controller+0x338)!=provider||Read<int>(block+8)<=0||Read<int>(block+0xC)<=0||
               Pointer(provider)!=expectedImage+0x552E100||Read<int>(provider+0x60)!=5||Read<byte>(provider+0x80)!=1||
               Read<byte>(provider+0x81)!=affects||Read<ulong>(provider+0x90)!=count||Read<ulong>(provider+0x98)!=capacity||Pointer(provider+0xA0)!=storage||
               bitmaps.Any(v=>Read<ulong>(v.at)!=v.bits)||values.Any(v=>Read<uint>(v.at+8)!=v.index||Read<byte>(v.at+0x30)!=v.selected))return false;
            if(affects!=0)mask|=1u<<15;
            result=new(controller,provider,mask);return true;
        }
        catch{return false;}
    }

    // Called only by the original route queue on its verified owning thread.
    // This is the actual original Map UI action, not direct settings writes.
    // The display category/checkboxes change just as they do in that UI.
    static bool ApplyGalaxyStarClassRouteFilter(Snapshot frame,uint mask)
    {
        if(!ValidGalaxyRouteStarMask(mask)||!Enabled()||!inGame||!frame.valid||frame.entity==0||
           owningThread==0||GetCurrentThreadId()!=owningThread||!FindGalaxyServices(frame,out var services))return false;
        try
        {
            var type=Read<uint>(image+0x5FDB224);var component=RegisteredComponent(services.registry,type);
            if(!CopyGameRouteOptions(component,image,out var main,out _)||!CopyGalaxyRouteStarClassState(main,image,out var before))return false;
            var current=Current();if(!current.valid||current.entity!=frame.entity||current.referenceWorld!=frame.referenceWorld||
                Read<uint>(image+0x5FDB224)!=type||RegisteredComponent(services.registry,type)!=component)return false;
            ((delegate* unmanaged<nuint,uint,uint,void>)(image+0x3A68F60))(main,5,mask);
            current=Current();
            return current.valid&&current.entity==frame.entity&&current.referenceWorld==frame.referenceWorld&&
                Read<uint>(image+0x5FDB224)==type&&RegisteredComponent(services.registry,type)==component&&
                CopyGameRouteOptions(component,image,out var afterMain,out _)&&afterMain==main&&
                CopyGalaxyRouteStarClassState(main,image,out var after)&&after.mapController==before.mapController&&
                after.provider==before.provider&&after.mask==mask;
        }
        catch{return false;}
    }
}